语言
-
python补习
装饰器 函数装饰器 什么是装饰器 装饰器是python的一种高级语法,本质上是函数包装器,可以在不修改函数代码的前提下为函数添加额外功能如日志记录、性能计时、权限校验,也可以修改函数的输入和输出。装饰器通过@装饰器名语法应用与函数,也是一种语法糖,简化包装的代码。 基本语法与原理 装饰器是一个接收函数作为参数,并返回新函数的函数。当用@decorator修饰函数func时,相当于执行func=decorator(func),即原函数被替换为装饰器返回的新函数。 # 定义装饰器:打印函数调用信息 def log_decorator(func): def wrapper(*args, **kwargs): print(f"调用函数: {func.__name__}") # 额外功能:打印日志 result = func(*args, **kwargs) # 执行原函数 print(f"函数 {func.__name__} 执行完毕") return result # 返回原函数结果 return wrapper # 应用装饰器 @log_decorator def add(a, b): return a + b # 调用函数 add(1, 2) 上面打印的输出为 调用函数: add 函数 add 执行完毕 3 可以看到,相当于给add函数做了一层包装。这里 log_decorator 为 add 函数添加了“调用日志”功能,原 add 函数代码未做任何修改。 带参数的装饰器 如果装饰器需要自定义参数(如 @parser.wrap() 中的空括号),需在基础装饰器外再嵌套一层参数接收函数。 # 带参数的装饰器:自定义日志前缀 def log_decorator(prefix="LOG"): def decorator(func): def wrapper(*args, **kwargs): print(f"[{prefix}] 调用函数: {func.__name__}") # 使用装饰器参数 result = func(*args, **kwargs) return result return wrapper return decorator # 应用装饰器(传递参数) @log_decorator(prefix="DEBUG") def multiply(a, b): return a * b multiply(3, 4) # 输出: [DEBUG] 调用函数: multiply → 返回 12 装饰器在 Python 中非常常用,典型场景包括: 日志记录:自动记录函数调用、参数、返回值; 性能计时:统计函数执行时间; 权限校验:检查用户是否有权限调用函数; 输入/输出处理:自动转换参数类型、格式化返回值; 资源管理:自动打开/关闭文件、数据库连接等。 类装饰器 前面描述了函数装饰器,还有类的装饰器。类的装饰器是通过修改类的定义、添加/覆盖方法或属性,或返回一个新类,来增强类的功能,与函数装饰器(修饰函数)不同,类装饰器专注于修饰类本身。类装饰器通过 @装饰器名 语法应用于类,是一种“语法糖”,简化了类的动态修改逻辑。 类装饰器是一个接收类作为参数,并返回新类的函数。当用 @decorator 修饰类 MyClass 时,相当于执行 MyClass = decorator(MyClass),即原类被“替换”为装饰器返回的新类。 简单类装饰器示例 # 定义类装饰器:为类添加一个属性和方法 def add_greeting(cls): cls.greeting = "Hello from decorator!" # 新添加类属性 def say_hello(self): # 新定义要添加的实例方法 return f"{self.greeting} I'm {self.name}." cls.say_hello = say_hello # 将方法绑定到类 return cls # 返回修改后的类 # 应用装饰器 @add_greeting class Person: def __init__(self, name): self.name = name # 使用装饰后的类 p = Person("Alice") print(p.greeting) # 输出:Hello from decorator! print(p.say_hello()) # 输出:Hello from decorator! I'm Alice. 内置装饰器@dataclass @dataclass 是 Python 标准库 dataclasses 提供的内置类装饰器,用于快速定义数据存储类(Data Class),核心作用是: 自动生成 init 方法:无需手动编写 def init(self, robot, dataset, ...): ...,装饰器会根据类字段自动生成。 自动生成 repr、eq 等方法:方便打印实例(如 print(cfg))和比较实例是否相等。 支持字段默认值和类型注解:如 teleop: TeleoperatorConfig | None = None 中的默认值和类型约束。 先来看看如果不适用@dataclass装饰器,定义一个普通的类,需要手动编写init,repr等方法,如下 class DatasetConfig: def __init__(self, repo_id: str, num_episodes: int = 50): self.repo_id = repo_id # 手动绑定 self.xxx self.num_episodes = num_episodes def __repr__(self): # 手动编写打印逻辑 return f"DatasetConfig(repo_id={self.repo_id!r}, num_episodes={self.num_episodes!r})" # 使用 cfg = DatasetConfig("aliberts/record-test", 2) print(cfg) # 输出:DatasetConfig(repo_id='aliberts/record-test', num_episodes=2) 如果使用了@dataclass,则不需要编写init等方法,但是需要添加属性的类型注解声明,如下面repo_id,num_episodes。如果有默认值的,如下的int=50,可选传递参数,如果没有默认值的,必现要传递参数如repo_id。 from dataclasses import dataclass @dataclass class DatasetConfig: repo_id: str # 必选字段(无默认值) num_episodes: int = 50 # 可选字段(默认值 50) # 使用(效果与普通类完全一致) cfg = DatasetConfig("aliberts/record-test", 2) print(cfg) # 自动生成 __repr__:DatasetConfig(repo_id='aliberts/record-test', num_episodes=2) @dataclass提供初始化后回调方法,在init执行完毕后自动调用,用于字段校验,动态修改字段值等。 from dataclasses import dataclass @dataclass class DatasetConfig: repo_id: str # 必选字段(无默认值) num_episodes: int = 50 # 可选字段(默认值 50) def __post_init__(self): if self.repo_id is None: raise ValueError("You need to provide a repo_id as argument.") 函数返回类型注解 函数返回类型注解是python 3.0+引入的类型提示语法,用于显式声明函数预期返回值的类型。它不会改变函数的运行逻辑,只是为了提升代码的可读性、支持IDE智能提示,便于静态代码检查工具检测潜在错误。其语法格式为如下: def 函数名(参数: 参数类型) -> 返回值类型: # 函数逻辑 return 返回值 返回类型注解通过->类型语法声明,位于函数定义参数列表之后、冒号:之前。 def record(cfg: RecordConfig) -> LeRobotDataset: # ... 函数逻辑 ... return dataset # dataset 是 LeRobotDataset 实例 这里 -> LeRobotDataset 表示:record 函数执行完毕后,预期返回一个 LeRobotDataset 类的实例。 注解都有哪些类型了,除了基础的int、float、str、bool、None(空)这几个类型外,还有容器类型、组合类型、特殊类型等。 容器类型 列表,list[值类型] ,用于标注列表、字典、元组等容器的元素类型,Python 3.9+ 支持直接用 list[int] 形式,旧版本需从 typing 模块导入(如 List[int])。 motor_names: list[str] = ["shoulder_pan", "elbow_flex"] # 字符串列表 positions: list[float] = [0.2, 0.5, -0.3] # 浮点数列表 字典,dict[键类型, 值类型]如下示例 def _motors_ft(self) -> dict[str, type]: # 键为字符串,值为类型对象(如 float) return {f"{motor}.pos": float for motor in self.bus.motors} 元组,tuple[类型1, 类型2, ...],如下示例: def _cameras_ft(self) -> dict[str, tuple]: # 值为元组(高、宽、通道数) return {cam: (height, width, 3) for cam in self.cameras} # 更精确标注:tuple[int, int, int](高、宽、3通道) 集合类型,set[元素类型],如下示例唯一电机ID集合。 motor_ids: set[int] = {1, 2, 3, 4, 5, 6} # 整数集合 组合类型 Union,Union[类型1, 类型2, ...],允许整数或字符串的参数 from typing import Union def get_motor(motor_id: Union[int, str]) -> Motor: # motor_id 可为 int 或 str ... # Python 3.10+ 简写: def get_motor(motor_id: int | str) -> Motor: ... Option,Optional[类型],(等价于 Union[类型, None]),可能为None的配置参数。 from typing import Optional def connect(port: Optional[str] = None) -> None: # port 可为字符串或 None ... 特殊类型 Any,任意类型,关闭类型检查,允许任何类型(常用于动态数据,如lerobot代码中 get_observation 返回 dict[str, Any]) from typing import Any def get_observation(self) -> dict[str, Any]: # 值可为任意类型(电机位置/图像等) ... Callable,Callable[[参数类型1, 参数类型2], 返回值类型],接受函数作为参数。 from typing import Callable def calibrate(callback: Callable[[str], None]) -> None: # callback 是 (str) -> None 的函数 callback("Calibration done") type,Type[类型](标注“类型本身”而非实例,如lerobot代码中 dict[str, type]),接受类作为参数。 from typing import Type def create_robot(robot_class: Type[Robot]) -> Robot: # robot_class 是 Robot 的子类 return robot_class() 配置选择注册机制 以draccus.ChoiceRegistry为例说明,draccus.ChoiceRegistry 是 draccus 配置框架提供的子类注册与动态选择机制。它允许将基类的多个子类注册为“可选选项”,并通过配置参数(如命令行、配置文件)动态选择具体子类。在工程中,这一机制用于实现 “同一接口,多种实现” 的灵活配置(例如不同机器人型号共享 RobotConfig 接口,但有各自的硬件参数实现)。 注册与选择流程 1. 基类:继承ChoiceRegistry并声明接口。如示例基类(如 RobotConfig)继承 draccus.ChoiceRegistry,作为所有子类的“公共接口”。它定义通用字段和方法,不包含具体实现细节。 from dataclasses import dataclass import abc import draccus @dataclass(kw_only=True) class RobotConfig(draccus.ChoiceRegistry, abc.ABC): # 继承 ChoiceRegistry # 通用字段(所有子类共享) id: str | None = None # 机器人标识 calibration_dir: Path | None = None # 校准文件路径 @property def type(self) -> str: # 获取当前子类的注册名称(核心方法) return self.get_choice_name(self.__class__) 2. 子类:注册为可选项。每个具体实现(如不同机器人型号)定义一个 RobotConfig 的子类,补充特有字段和逻辑。draccus 会自动将子类注册为一个可选选项,如下: 例如,so101_follower 机器人的配置子类: # SO101FollowerConfig(so101_follower 型号) @dataclass(kw_only=True) class SO101FollowerConfig(RobotConfig): port: str # 型号特有字段(通信端口) disable_torque_on_disconnect: bool = True # 型号特有字段(扭矩控制) # KochFollowerConfig(koch_follower 型号) @dataclass(kw_only=True) class KochFollowerConfig(RobotConfig): ip_address: str # 型号特有字段(以太网通信地址) timeout_ms: int = 500 # 型号特有字段(通信超时) SO101FollowerConfig/KochFollowerConfig继承了RobotConfig,而RobotConfig继承了draccus.ChoiceRegistry。 3. 动态选择:通过配置参数指定子类。用户通过配置参数(如命令行 --robot.type=so101_follower)指定要使用的子类。draccus 会: 根据参数值(so101_follower)查找注册的子类; 实例化该子类,并将其他配置参数(如 --robot.port=/dev/ttyACM1)映射到子类字段; 返回实例化后的子类对象,作为业务逻辑的输入。 # 命令行参数示例 python -m lerobot.record \ --robot.type=so101_follower \ # 选择 SO101FollowerConfig 子类 --robot.id=black \ # 设置通用字段 id --robot.port=/dev/ttyACM0 \ # 设置型号特有字段 port --robot.disable_torque_on_disconnect=true # 设置型号特有字段 动作先行思维 C语言的风格是写法是条件先行,再写动作。而python支持动作先行写法,再补充条件,主要是为了简写。请看下面示例。 A if cond else B # 简洁写法(条件表达式) teleop = make_teleoperator_from_config(cfg.teleop) if cfg.teleop is not None else None # 等价传统写法(if-else 块) if cfg.teleop is not None: teleop = make_teleoperator_from_config(cfg.teleop) else: teleop = None 使用的简洁方法是: A if cond else B。 or短路运算 # 例:若 config_path 为空,则默认使用 "./config.json" config_path = user_provided_path or "./config.json" for循环 C 的 for 循环强调“初始化→条件→增量”的控制流,而 Python 的 for 更关注“迭代对象→元素处理”,动作(循环体)直接跟在迭代逻辑后。 # 例:遍历数据集并处理每个帧 for frame in dataset.frames: process_frame(frame) # 动作(循环体)直接跟在迭代逻辑后 Python 无需显式初始化索引、判断终止条件或手动增量(如 i++),迭代逻辑由“可迭代对象”(如列表、字典、生成器)内部处理。 列表推导式 结构是列表推导式:[表达式 for 变量 in 可迭代对象 if 条件] Python 的列表推导式将“对元素的处理动作”放在最前面,直接表达“要生成什么样的列表”,而非 C 中“如何生成列表”的步骤式逻辑。 # 例:筛选偶数并计算平方(动作:x**2,条件:x%2==0) even_squares = [x**2 for x in range(10) if x % 2 == 0] # 结果:[0, 4, 16, 36, 64] 结构拆解: 动作:(x**2),定义每个元素的转换方式(先明确“要做什么”); 迭代逻辑:(for x in range(10)),从哪里获取元素; 条件:(if x\%2 =\= 0),筛选元素的规则,后补充限制条件。 也可以直接做赋值,看下面例子 @dataclass class Example: src: List[int] tgt: List[int] 收集列表直接赋值为data data = [Example(s,t)] for s, t in paris if len(s) > 0] 等价于 for s, t in pairs: if len(s) > 0: src_ids = s; tgt_idg = s; data.append(Example(s,t)) 字典推导式 核心逻辑是:{新键: 新值 for 键, 值 in 迭代器 if 条件} 先定义“键和值的生成动作”,再说明迭代范围和筛选规则,适用于快速构建字典。示例:将遥操作器原始动作(如 {"shoulder": 0.2, "gripper": 0.9})转换为带前缀的数据集格式: # 原始遥操作动作 teleop_action = {"shoulder": 0.2, "elbow": 0.5, "gripper": 0.9} # 字典推导式:先定义键值动作(添加前缀),再迭代 dataset_action = { f"action.{key}": value # 动作:键添加前缀,值保持不变 for key, value in teleop_action.items() # 迭代范围:遥操作动作字典 if key != "gripper" # 筛选条件:排除 gripper(假设无需记录) } print(dataset_action) # 输出:{"action.shoulder": 0.2, "action.elbow": 0.5} 再来看看几个例子: features = {} joint_fts = {key: ftype for key, ftype in hw_features.items() if ftype is float} 遍历 hw_features 的所有键值对(key, ftype),仅保留 值为 float 类型 的键值对(即电机角度等浮点型特征)。若hw_features 含 {"shoulder.pos": float, "camera": (480,640,3)},则 joint_fts 为 {"shoulder.pos": float}。函数的作用就是筛选电机特征。实际打印如下: joint_fts : {'shoulder_pan.pos': <class 'float'>, 'shoulder_lift.pos': <class 'float'>, 'elbow_flex.pos': <class 'float'>, 'wrist_flex.pos': <class 'float'>, 'wrist_roll.pos': <class 'float'>, 'gripper.pos': <class 'float'>} cam_fts = {key: shape for key, shape in hw_features.items() if isinstance(shape, tuple)} 遍历 hw_features,仅保留 值为元组类型 的键值对(即相机尺寸等元组特征,如 (高, 宽, 通道数))。示例:若 hw_features 含 {"camera": (480,640,3)},则 cam_fts 为 {"camera": (480,640,3)}。函数的作用就是筛选相机特征。 cam_fts : {'handeye': (480, 640, 3), 'fixed': (480, 640, 3)} Action Features: {'action': {'dtype': 'float32', 'shape': (6,), 'names': ['shoulder_pan.pos', 'shoulder_lift.pos', 'elbow_flex.pos', 'wrist_flex.pos', 'wrist_roll.pos', 'gripper.pos']}} -
C++回顾
平时用C++比较少,最近项目需要用到C++,现简单再回顾一下。 单例模式 在某些场景下,一个类只需要有一个实例就足够了,例如配置管理类、日志记录器、数据库连接池等。使用单例模式可以避免创建多个实例导致的资源浪费、数据不一致等问题。 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在程序运行期间,这个类的实例始终只有一个,所有对该类实例的访问都通过这个全局访问点进行。 #include <iostream> class Board { private: // 私有构造函数,防止外部实例化 Board() {} // 禁止拷贝构造函数 Board(const Board&) = delete; // 禁止赋值运算符 Board& operator=(const Board&) = delete; static Board* instance; public: // 静态方法,用于获取唯一实例 static Board& GetInstance() { if (instance == nullptr) { instance = new Board(); } return *instance; } void printMessage() { std::cout << "This is the Board instance." << std::endl; } }; // 初始化静态成员变量 Board* Board::instance = nullptr; int main() { Board& board = Board::GetInstance(); board.printMessage(); return 0; } 智能指针 在传统的 C++ 中,使用 new 运算符手动分配内存,需要使用 delete 运算符手动释放内存。如果忘记释放内存,就会导致内存泄漏。使用智能指针可以自动管理对象的生命周期,避免内存泄漏的问题。 std::make_unique 是 C++14 引入的一个函数模板,用于创建 std::unique_ptr 对象。std::unique_ptr 是一种智能指针,它对所指向的对象拥有唯一所有权,即同一时间只能有一个 std::unique_ptr 指向同一个对象。当 std::unique_ptr 被销毁时,它所指向的对象也会被自动销毁。 #include <iostream> #include <memory> class MyClass { public: MyClass() { std::cout << "MyClass constructor" << std::endl; } ~MyClass() { std::cout << "MyClass destructor" << std::endl; } void doSomething() { std::cout << "Doing something..." << std::endl; } }; int main() { // 使用 std::make_unique 创建 std::unique_ptr auto ptr = std::make_unique<MyClass>(); ptr->doSomething(); // 当 ptr 离开作用域时,MyClass 对象会自动销毁 return 0; } Lambda 表达式 Lambda 表达式的主要优点是简洁性和灵活性。在一些场景下,我们只需要一个简单的函数,而且这个函数只在某个特定的地方使用一次,使用 Lambda 表达式可以避免定义一个单独的命名函数,使代码更加简洁。 Lambda 表达式是 C++11 引入的一种匿名函数机制,它允许在代码中定义一个临时的、没有名称的函数。Lambda 表达式可以捕获外部变量,从而在函数内部使用这些变量。 [capture list] (parameter list) mutable(可选) -> return type(可选) { function body } 实例,lambda一般用于设置回调函数。 codec->OnInputReady([this, codec]() { // 捕获列表 [this, codec] 表示捕获当前对象和 codec 变量 xEventGroupSetBitsFromISR(...); return ...; }); 移动语义std::move 在某些情况下,对象的拷贝操作可能会非常昂贵,例如对象包含大量的数据或者动态分配的内存。使用移动语义可以避免这些不必要的拷贝操作,提高程序的性能。 移动语义是 C++11 引入的一个重要特性,它允许将对象的资源所有权从一个对象转移到另一个对象,避免不必要的拷贝操作。std::move 是一个标准库函数,用于将左值转换为右值引用,从而触发移动构造函数或移动赋值运算符。 #include <iostream> #include <vector> class MyVector { private: std::vector<int> data; public: MyVector(const std::vector<int>& vec) : data(vec) { std::cout << \"Copy constructor called\" << std::endl; } // 移动构造函数 MyVector(MyVector&& other) noexcept : data(std::move(other.data)) { std::cout << \"Move constructor called\" << std::endl; } void printSize() { std::cout << \"Size: \" << data.size() << std::endl; } }; int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; MyVector v1(vec); // 使用 std::move 调用移动构造函数 MyVector v2(std::move(v1)); v2.printSize(); return 0; } 在上述代码中,std::move(v1) 将 v1 转换为右值引用,从而调用 MyVector 的移动构造函数。移动构造函数将 v1 的 data 资源所有权转移到 v2,避免了不必要的拷贝操作。 模版 C++ 模板(Template)是一种强大的编程特性,它允许你编写泛型代码,使得代码能够在不同数据类型上重复使用。模板支持函数模板和类模板,它们能在编译时根据具体类型生成代码,从而提高代码的复用性和灵活性。 函数模版 #include <iostream> using namespace std; template <typename T> T add(T a, T b) { return a + b; } //template <typename T>:这是函数模板的声明。T 是类型参数,表示函数可以处理任何类型。 //T add(T a, T b):定义了一个接受两个 T 类型参数并返回一个 T 类型结果的函数。 int main() { cout << add(3, 5) << endl; // 调用模板函数,类型为 int cout << add(3.5, 5.5) << endl; // 调用模板函数,类型为 double return 0; } 类模版 #include <iostream> using namespace std; template <typename T> class Box { private: T value; public: void setValue(T v) { value = v; } T getValue() { return value; } }; //template <typename T>:定义类模板,T 是类型参数。 //T value:类中的成员变量 value 是类型 T。 //setValue(T v) 和 getValue():成员函数也使用模板类型 T。 int main() { Box<int> intBox; intBox.setValue(5); cout << intBox.getValue() << endl; // 输出:5 Box<double> doubleBox; doubleBox.setValue(3.14); cout << doubleBox.getValue() << endl; // 输出:3.14 return 0; } -
Javascript笔记
JS JS简介 JS实现网页交互过程 javascript: 1.让用户和网页进行交互 网站登录功能, 点击,弹出一个按钮 滚动加载 返回底部 2.交互三要素 目标:网页中的那些html元素 事件:触发了什么事件 事件处理程序:针对事件要做什么要的动作 <body> <button id=\"chsize\"> 增大字体 </button> <script> document.querySelector(\"#chsize\").addEventListener(\'click\',function(e)) { alert(\"按钮被单击了\") document.querySelect(\'body\').style.fontSize = \'30px\'; /*具体的事件处理程序*/ } </script> </body> JS脚本引入方式 1.内敛脚本 <button onclik=\"alert(\'我被点击了\');\"> </button> 2.内部脚本 如十三章节事例 3.外部脚本 创建一个xxx.js <script src=\"xxxx/xxx.js\"> </script> 脚本的引用可以放在任意位置 为了效率一般情况下放在</body>的上方 访问网页最终得到什么 网页开发者模式:网络面板 network->response可以看源码 静态网页、资源和动态网页区别 静态网页、资源:网页的内容直接展示,文字、图片,脚本 动态网页:先执行,才会得到结果。 参考:https://liaoxuefeng.com/books/javascript/introduction/index.html JS函数 普通函数 function add(num1, num2) { return num1 + num2; } 通过 function 关键字进行定义,有返回值,与C语言相比,省略的变量的类型。 匿名函数 var add = function(a, b) { return a + b; }; // 调用匿名函数 console.log(add(2, 3)); // 输出 5 匿名函数是指没有名称的函数。它通常用于用作回调函数或立即调用函数表达式(IIFE)等场景。匿名函数是JavaScript中的常见编程模式,其目的是不污染全局命名空间的情况下定义和使用函数。 自调用函数 自调用函数实际是匿名函数的变体,即匿名函数立即调用执行。 (function() { // 这里是函数体 })(); 定义了一个函数并且会立即调用它执行,没有函数名称,它仍然可以执行其所需的操作。 匿名函数被圆括号包裹起来,紧接着又跟上一个空的圆括号,这样就创建了一个立即执行的函数。如果我们需要在函数内部传入参数,可以在定义函数时给它传入参数: (function(x, y) { console.log(x + y); })(2, 3); // 输出5 自调用函数适用于需要在定义时就立即执行而不保存函数引用的场合。它可以被用于命名空间以及防止变量污染等编程模式中。 箭头函数 简写函数表达式的语法形式,在匿名函数的基础上,把function也去掉了,它的语法形式如下, (argument1, argument2, …, argumentN) => { // 函数体 } 特点如下: 简写语法:省略了function关键字,使用箭头“=>”来代替。 省略return关键字:如果函数体只有一行语句,则可以省略花括号和return关键字,直接返回这一行语句的结果。 this绑定:箭头函数中的“this”指向的是定义时所在的对象,而不是调用时的对象。 下面 // 传统函数声明 function foo(x, y) { return x + y; } // 箭头函数 const bar = (x, y) => { return x + y; } // 简写语法 const baz = (x, y) => x + y; // this绑定的示例 const person = { name: \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'Alice\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\', sayHello: function() { console.log(`Hello, my name is ${this.name}`); }, sayBye: () => { console.log(`Bye, my name is ${this.name}`); //没有this关键词,name无效 } } person.sayHello(); // 输出:Hello, my name is Alice person.sayBye(); // 输出:Bye, my name is undefined 回调函数 回调函数是作为参数传递给另一个函数的函数。当这个外部函数执行到某个特定阶段或满足某种条件时,就会调用(执行)这个作为参数的函数。简单来说,回调函数就是把函数当作一个变量一样传递给其他函数,让其他函数来决定何时执行它。 事件处理是回调函数的常见应用。例如,当用户点击一个按钮时,我们可以通过回调函数来定义点击按钮后要执行的操作。 const button = document.getElementById(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'myButton\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'); // 定义一个回调函数,用于处理按钮点击事件 function handleClick() { console.log(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'按钮被点击啦,这是通过赋值方式使用的回调函数在起作用哦!\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'); } // 通过赋值的方式,将回调函数绑定到按钮的onclick属性上 button.onclick = handleClick; 首先,通过 document.getElementById(\'myButton\') 获取到页面中 id 为 myButton 的按钮元素,并将其赋值给变量 button。 接着,定义了一个名为 handleClick 的函数,这个函数就是回调函数,其内部代码实现了当按钮被点击时要执行的具体逻辑,在这里只是简单地在控制台输出一段提示信息。 最后,通过 button.onclick = handleClick 这种赋值的方式,将 handleClick 函数赋值给按钮的 onclick 属性。当用户点击这个按钮时,浏览器就会自动调用 handleClick 函数,从而执行函数内部定义的代码,实现了基于回调函数的事件处理。 上面的方式还可以进行简写,直接使用箭头函数,函数名也省掉了。 const button = document.getElementById(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'myButton\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'); // 直接使用箭头函数表达式赋值给按钮的onclick属性,省略函数名 button.onclick = e => { console.log(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'按钮被点击啦,直接使用箭头函数表达式作为回调函数在起作用哦!\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'); }; 回调函数常用语事件处理。而且常与匿名函数、箭头函数一起配合。匿名函数和箭头函数可以省略掉返回值。 嵌套函数 JS嵌套函数指在一个函数内部定义一个或多个函数。这些内部函数可以被外部函数调用,也可以在内部函数内部再次定义其它函数。 function outer() { console.log(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'outer function\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'); function inner1() { console.log(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'inner1 function\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'); } function inner2() { console.log(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'inner2 function\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'); } inner1(); inner2(); } // 调用外部函数 outer(); 上面的代码中,定义了一个外部函数outer(),在其中定义了两个内部函数inner1()和inner2()。在outer()被调用时,内部函数inner1()和inner2()也被调用。内部函数可以访问外部函数的变量和参数,而外部函数不能访问内部函数的变量。通过嵌套函数,可以有效地组织代码,并使代码更易于阅读和维护。 高阶函数 函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数,如下所示add函数中,接收了f函数作为参数。 function add(x, y, f) { return f(x) + f(y); } 调用add(-5, 6, Math.abs)时,参数x,y和f分别接收-5,6和函数Math.abs,根据函数定义,可以推导计算过程为: x = -5; y = 6; f = Math.abs; f(x) + f(y) ==> Math.abs(-5) + Math.abs(6) ==> 11; return 11; 闭包 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。 function outerFunction() { let counter = 0; function innerFunction() { counter++; console.log(counter); } return innerFunction; } let increment = outerFunction(); //将innerFunction作为函数值返回赋值为increment。 increment(); // 输出 1 increment(); // 输出 2 increment(); // 输出 3 参考: https://blog.csdn.net/weixin_65789931/article/details/132697866 https://liaoxuefeng.com/books/javascript/function/closure/index.html -
HTML+CSS学习随记
HTML基本结构 示例1 <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"> 1.这是 HTML 4.01 的文档类型声明,表示该文档遵循 HTML 4.01 标准。它告知浏览器页面的解析方式 <html lang=\"zh\"> 2.指定文档的主要语言是中文。lang=\"zh\" 对 SEO 和屏幕阅读器有帮助。 3.head部分包含文档的元数据(metadata),如文档字符编码、标题、样式表和脚本等。这部分不会直接显示在网页上,但它影响页面的显示方式和功能。 <head> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> 3.1 meta标签:用于定义页面的字符集、视口设置、作者信息等。 <title>网页标题</title> 3.2 title标签:设置网页的标题,显示在浏览器的标签栏中。 <link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">,这种方式是 使用的包含外部样式,还可以使用在 <head> 中使用 <style> 标签来包含内部样式。 3.3 link标签:用于链接外部资源,如 CSS 样式表。 <script type=\"text/javascript\" src=\"script.js\"></script> 3.4 script标签:引入外部 JavaScript 文件,或内嵌 JavaScript 代码。 </head> 4. body部分包含了网页的实际内容,如文本、图片、链接等。所有用户在浏览器中看到的内容都位于body标签内。 <body> <div id=\"header\"> <h1>欢迎访问我的网页</h1> </div> 4.1 div标签:用于定义网页的不同区域。虽然 HTML4中没有HTML5 的语义化标签(如 <header>, <footer> 等),但<div>是常用的布局元素。 4.2 h标签:定义标题,<h1> 是最高级别的标题,数字越大,标题级别越低。对于页面结构和 SEO 来说,合理使用这些标签有助于提高页面的可读性和搜索引擎的抓取。 <div id=\"nav\"> <ul> <li><a href=\"#home\">首页</a></li> <li><a href=\"#about\">关于</a></li> <li><a href=\"#services\">服务</a></li> </ul> </div> 4.3 ul标签:表示无序列表,<li> 表示列表项。在HTML4中,常常使用这种方式来创建导航菜单。 <div id=\"content\"> <p>这是网页的主体内容。</p> </div> 4.4 p标签:定义段落,通常用于包含一段文本。 <div id=\"footer\"> <p>© 2024 我的公司</p> </div> </body> 5. 属性:在标签里面的如name,id,src,href这些都是标签的属性。属性是附加在 HTML 元素上的信息,用于修改或指定元素的行为和外观。属性总是写在开始标签内,并且以键值对的形式存在。属性可以控制元素的某些特性(如样式、链接、身份、动作等)。 6. 标签和元素的概念与区别 6.1 标签是是 HTML 语法中用于定义元素的标记,通常由尖括号包围,并且具有起始标签和结束标签。标签是构成HTML元素的基本单元。 6.2 元素是由标签、内容、以及可能的属性组成的完整结构。可以认为,标签是元素的一部分,元素包括了标签本身以及它的内容和属性。 </html> 主要构成有: 文档类型声明!DOCTYPE> HTML根元html 头部head: 包含页面的元数据,例如字符编码、页面标题、样式等。 主体body:包含网页的实际内容和展示。 在HTML网页制作中,CSS和JS有着重要的作用。 CSS主要用于网页的 样式设计 和 布局控制。通过 CSS,开发者可以控制网页的外观,包括字体、颜色、尺寸、位置、布局等。 JavaScript 是一种 编程语言,主要用于网页的 交互功能 和 动态效果。它使得网页能够响应用户的操作,实现动态内容、表单验证、动画效果等。 对于CSS 引入有以下3中方法: - 内联样式:<p style=\"color:red;\"> - 内嵌样式:<style> 标签放在 <head> 中 - 外部样式:使用 <link> 标签引入 .css 文件 对于JavaScript 引入,有以下3中方法: - 内联 JavaScript:直接写在 HTML 标签事件中(如 onclick) - 内嵌 JavaScript:<script> 标签放在 <head> 或 <body> 中 - 外部 JavaScript:使用 <script src=\"script.js\"></script> 引入外部 .js 文件 示例2 <!DOCTYPE html> <html lang=\"en\"> <head> <meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <title>HTML4 示例页面</title> <!-- 内部CSS样式 --> <style> body { font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0; } header { background-color: #333; color: white; text-align: center; padding: 10px 0; } h1 { font-size: 2em; } .container { width: 80%; margin: 0 auto; padding: 20px; } p { font-size: 1.2em; } /* 外部CSS样式的链接 */ @import url(\'styles.css\'); </style> <!-- 引入外部JavaScript文件 --> <script src=\"scripts.js\" type=\"text/javascript\"></script> </head> <body> <header> <h1>HTML4 示例页面</h1> </header> <div class=\"container\"> <p>欢迎来到我的网站!这是一个简单的 HTML4 示例页面。</p> <!-- 有序列表 --> <ol> <li>第一个项目</li> <li>第二个项目</li> <li>第三个项目</li> </ol> <!-- 表单 --> <form action=\"submit_form.php\" method=\"post\"> <label for=\"name\">名字:</label> <input type=\"text\" id=\"name\" name=\"name\" required> <br><br> <label for=\"email\">邮箱:</label> <input type=\"email\" id=\"email\" name=\"email\" required> <br><br> <button type=\"submit\">提交</button> </form> <p>这是一个链接:<a href=\"https://www.example.com\" target=\"_blank\">访问 Example 网站</a></p> <!-- 图片展示 --> <img src=\"example.jpg\" alt=\"示例图片\" width=\"300\"> <button onclick=\"changeBackgroundColor()\">点击我改变背景色</button> </div> <script> // 外部JavaScript文件会包含一些交互功能 function changeBackgroundColor() { document.body.style.backgroundColor = \'#ffcccc\'; } </script> </body> </html> HTML简单入门 超文本标记语言 1. 标题 1.1 一级标题 <h1> xxxx < /h1> 1.2 二级标题 <h2> xxxx < /h2> 2.段落 <p> xxxx < /p> 3.插入图片 绝对地址方式:<img src=\"路径/xxx.jpg\"> ---效率更高点 相对地址方式:<img src=\"路径/xxx.jpg\" /> 重要概念 标签 从哪里开始,哪里结束 单标签:开始 <h1>, 结束</h1> 双标签:格式<img src=\"xxx/xxx.jpg\" />, /结束标签 标签属性 标签要设置的属性 标签属性: <img src=\"xxx.jpg\" />, src就是属性 id属性: <p id=\"zansan\">,可用于区分这个标签与其他标签 class属性: <p class=\"xxx\">,用于分类,常用CSS搭配使用。 title属性: <button title=\"Click me\">Submit</button> 描述了元素的额外信息 (作为工具条使用) style属性:规定元素的行内样式(inline style) 元素 由标签、内容、以及可能的属性组成的完整结构。可以认为,标签是元素的一部分,元素包括了标签本身以及它的内容和属性。元素以开始标签起始,结束标签终止。下面整个就是一个元素。 <h1> xxx < /h1> 乱码问题解决 编码、解码,网页乱码,查看文档源码乱码,UTF-8/ANSI/unicode,编码和解码格式要对应,否则显示异常,告诉浏览器当前使用的编码方式,如UTF-8。 常用标签 不同的标签,属性不一样,但是有一些公共属性,如id,class。 标题标签 下面是标题标签样式。 <h1>xxx< /h1> <h2>xxx< /h2> <h3>xxx< /h3> <h4>xxx< /h4> <h5>xxx< /h5> 段落标签 下面是段落标签 <p> xxx </p> 图片标签 <img src=\"xxx\" alt=\"xxxx\"> alt表示图片无法显示时,就显示什么文字;另外作用还可以告诉搜索引擎,图片内容是什么。 链接标签 <a href=\"https://www.baidu.com\">百度</a> 列表标签 有序列表 <ol> <li> </li> <li> </li> </ol> 无序列表 <ul> <li> </li> </ul> 布局标签 div div是一种块级元素(block-level element),用于对文档进行分组并添加样式或结构。div是“division”的缩写,表示页面中的一个逻辑分区或区域。它本身没有特定的语义含义,主要用于布局和样式设计。 <div id=\"container\" style=\"width:500px\"> <div id=\"header1\" style=\"background-color:#FDDDDD;\"> <p style=\"margin-bottom:0;\">标题</p> </div> <div id=\"menu\" style=\"background-color:#AFD700;height:200px;width:100px;float:left;\"> <b>菜单</b> </div> <div id=\"content\" style=\"background-color:#EEEEEE;height:200px;width:400px;float:left;\">正文</div> <div id=\"footer1\" style=\"background-color:#FFA500;clear:both;text-align:center;\">Footer</div> </div> 示例效果如下: span span标签是一种内联元素(inline element),用于对文档中的文本或部分内容进行分组,通常是为了应用样式或附加特定的属性。与 div 标签不同,span不会自动创建新的行,因此适合用于不影响文档流的情况下包裹文本或其他内联元素。 <p>这是一个 <span style=\"font-weight:bold\">网页</span> 的 <span style=\"font-style:italic\">测试</span>, 这是我的 <span style=\"background-color:yellow\">博客</span> <a href=\"https://www.laumy.tech\"> <span style=\"color:red; text-decoration:underline\">Laumy的技术栈</span> </a> </p> 示例如下: 常用元素 块级元素 <p>xxx</p> 可以换行 <div></div> 行内元素 <strong>xxx<strong>突出内容 注意的包含规则: 元素之间时可以相互嵌套 块级元素可以包含其他的行内元素 行内元素只能包含数据和其他行内元素 p元素不要包含其他块级元素 参考:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element CSS 想要对某个内容做样式,就需要先找到着力点,也就是要先选中内容;若有块元素标签如p等,就可以在属性直接描述,要是没有的话就用span包起来。 CSS的语法如下: 选择器{ 属性名: 属性值; 属性名: 属性值; } 选择器代表页面上的某类元素,选择器后一定是大括号。属性名后必须用冒号隔开,属性值后用分号(最后一个属性可以不用分号)。属性名和冒号之间最好不要有空格(经验)。如果一个属性有多个值的话,那么多个值用 空格 隔开。 (1)用span标签把内容包起来,表示要处理的内容,然后用属性如style描述。 <span style=\"font-weight:bold\"> </span> (2)p元素中的样式,如 <p style=\"xxxx\"> </p> (3)用class归类,在head内容中统一处理 <!DOCTYPE html> <html lang=\"en\"> <head> <style> .jiacu { font-weight:bold } </style> </head> <body> <p class=\"jiacu\"> xxxxx </p> <p class=\"jiacu\"> xxxxx </p> </body> </html> CSS的三种方式 1. 内联样式(style标签属性):<p style=\"color:red;\"> 2. 内嵌样式(head+ style + class的方式):<style> 标签放在 <head> 中 3. 外部样式:使用 <link> 标签引入 .css 文件 引用外部CSS文件的方式 (1)创建一个xxx.css @charset \"UTF-8\"; .jiacu { font-weight:bold } (2) 在html文件中引用 <link rel=\"stylesheet\" href=\"http:xxxx/xxx.css\"> CSS选择器 id选择器 id 选择器可以为标有特定id 的HTML元素指定特定的样式。HTML元素以id属性来设置id选择器,CSS 中 id 选择器以 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" 来定义。以下的样式规则应用于元素属性 id=\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"para1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\": #para1 { text-align:center; color:red; } 注意id不要以数字开头,有些浏览器有兼容性问题。 class选择器 .center { text-align:center; } class 选择器用于描述一组元素的样式,class 选择器有别于id选择器,class可以在多个元素中使用。class 选择器在 HTML 中以 class 属性表示, 在 CSS 中,类选择器以一个点 . 号显示:在以下的例子中,所有拥有 center 类的 HTML 元素均为居中。 通用选择器 p { ---选中所有的p元素 font-style:italic } 通配符*选择器 *{ margin-left:0px; margin-top:0px; } 通用选择器,将匹配任何标签。不建议使用,IE有些版本不支持,大网站增加客户端负担。效率不高,如果页面上的标签越多,效率越低,所以页面上不能出现这个选择器。 后代选择器 通过指定元素的后代关系选择 HTML 元素。后代选择器使用空格分隔元素名称。如下代码,div p 选择器将选择所有在 div 元素内的 p 元素。 样式 div p { font-weight: bold; } body代码 <div class=\"container\"> <p class=\"top-left\" id=\"device-id\"></p> <p class=\"top-right\" id=\"status\">waiting</p> </div> 上面的div p只对div中的p有效。 伪类选择器 CSS 伪类选择器(Pseudo-classes)用于选中元素的特定状态或特征,而不是通过常规的元素类型、类名或 ID 来选择。伪类使得你能够更精确地应用样式,比如当用户悬停在元素上、输入框为空、或元素处于被选中状态时,才应用样式。伪类通常以 : 符号开始。下面列出了一些常见的 CSS 伪类选择器及其使用方法。 a:link {color:#FF0000;} /* 未访问的链接 */ a:visited {color:#00FF00;} /* 已访问的链接 */ a:hover {color:#FF00FF;} /* 鼠标划过链接 */ a:active {color:#0000FF;} /* 已选中的链接 */ CSS文本样式 .xxx { color:red; --颜色 font-size:12px; --大小 font-weight:normal --粗细 text-decoration:underline; --画线,如下划线 line-height:20px; --行高 font-family:\'Arial Narrow\'; 字体格式 } CSS盒子模型 浏览器把html元素当成一个一个盒子,对一个盒子来设置其样式。 .test { border-top:2px solid blue; border-left:3px solid green; border-right:3px solid yellow; border-bottom:2px dashed red; padding-top:10px; ...... } CSS总结 CSS样式和html标签总结 选中要样式的内容,选中方法有 标签,盒子。 标签的作用:逻辑结构的作用,控制支点的作用(标识出来) span和div像是购物袋的作用,打包标识起来。 参考: https://www.runoob.com/css/css-id-class.html