首页
关于
Search
1
阿里云更换SSL证书
308 阅读
2
Nginx+Lua脚本控制负载均衡
176 阅读
3
地址相似度算法
166 阅读
4
【学习笔记】ES新特性
163 阅读
5
原生Hadoop搭建
140 阅读
默认分类
技术
JAVA
python
前端
大数据
运维
登录
Search
标签搜索
学习笔记
Javascript
前端
算法
负载均衡
Lua
Nginx
Kafka
Hive
Hbase
大数据
Hadoop
gitlab
CSS
HTML
ES语法
规则引擎
Drools
模型
springboot
枉自朝朝暮暮
累计撰写
12
篇文章
累计收到
1
条评论
首页
栏目
默认分类
技术
JAVA
python
前端
大数据
运维
页面
关于
搜索到
3
篇与
的结果
2023-05-07
【学习笔记】Javascript(二)
Javascript进阶1.字符串操作1.1.基本方法创建字符串// 字面量 const str1 = "Hello World"; // 构造函数 const str2 = new String("Hello World"); // 模板字符串(ES6) const name = "Alice"; const greeting = `Hello, ${name}!`; // "Hello, Alice!"基本属性与方法const str = "JavaScript"; console.log(str.length); // 字符串长度:10 console.log(str[0]); // 访问字符:'J' console.log(str.charAt(5)); // 'S'(索引从0开始) console.log(str.localeCompare("Java")); // 比较字符串:"JavaScript" > "Java" → 1查找与定位方法描述示例indexOf(searchValue)返回子字符串首次出现的索引,未找到返回 -1"apple".indexOf("p") → 1lastIndexOf(searchValue)返回子字符串最后一次出现的索引"apple".lastIndexOf("p") → 2includes(searchValue)是否包含子字符串(ES6)"apple".includes("app") → truestartsWith(searchValue)是否以指定字符串开头(ES6)"apple".startsWith("ap") → trueendsWith(searchValue)是否以指定字符串结尾(ES6)"apple".endsWith("le") → true截取与拼接方法描述示例concat(str1, str2)合并多个字符串"Hello".concat(" ", "World") → "Hello World"slice(start, end)截取子字符串(支持负数索引)"apple".slice(1, -1) → "ppl"substring(start, end)类似 slice,但负数索引会被视为 0"apple".substring(1, 3) → "pp"substr(start, length)从指定位置开始截取指定长度的字符串"apple".substr(1, 3) → "ppl"替换与分割方法描述示例replace(searchValue, newValue)替换子字符串(仅第一次匹配)"apple".replace("p", "x") → "axple"split(separator)按分隔符拆分为数组"a,b,c".split(",") → ["a", "b", "c"]trim()去除首尾空白字符" apple ".trim() → "apple"trimStart()/trimEnd()去除首/尾空白字符" apple ".trimStart() → "apple "大小写转换方法描述示例toLowerCase()转换为小写"Apple".toLowerCase() → "apple"toUpperCase()转换为大写"apple".toUpperCase() → "APPLE"1.2.高阶操作1. 字符串遍历const str = "hello"; for (let char of str) { console.log(char); // 分别输出 h e l l o }统计字符出现次数function countChars(str) { const counts = {}; for (const char of str) { counts[char] = (counts[char] || 0) + 1; } return counts; } console.log(countChars("aabbc")); // { a: 2, b: 2, c: 1 }解析 URL 参数function getUrlParams(url) { const params = {}; const parser = new URL(url); parser.searchParams.forEach((value, key) => { params[key] = value; }); return params; } const url = "https://example.com?name=Alice&age=25"; console.log(getUrlParams(url)); // { name: 'Alice', age: '25' }模板字符串(ES6)const price = 9.99; const message = `Price: $${price.toFixed(2)}`; // "Price: $9.99"1.3.正则表达式1.3.1.创建正则字面量const regex = /hello/; // 基础正则 const regexWithFlags = /\d+/ig; // 添加修饰符(i: 忽略大小写,g: 全局匹配)构造函数const regex = new RegExp("hello", "g"); // 动态创建正则修饰符修饰符作用i忽略大小写g全局匹配(找到所有匹配)m多行匹配(^和$匹配每行)s允许.匹配换行符1.3.2.常用符号元字符:元字符作用示例.匹配任意单个字符(除换行)/a.c/ 匹配 "abc", "a2c"^匹配字符串开头/^hello/ 匹配以"hello"开头$匹配字符串结尾/world$/ 匹配以"world"结尾*匹配前面字符 0 次或多次/ab*/ 匹配 "a", "ab", "abbb"+匹配前面字符 1 次或多次/ab+/ 匹配 "ab", "abbb"?匹配前面字符 0 次或 1 次/colou?r/ 匹配 "color"或"colour"{n}匹配前面字符恰好 n 次/a{3}/ 匹配 "aaa"{n,}匹配前面字符至少 n 次/a{2,}/ 匹配 "aa", "aaa"{n,m}匹配前一个字符 n 到 m 次/a{2,4}/ → 匹配 "aa"~"aaaa"()分组,捕获匹配内容/(ab)+/ → 匹配 "ab"、"abab"字符类:表达式作用\d匹配数字(0-9)\D匹配非数字\w匹配字母、数字、下划线\W匹配非字母、数字、下划线\s匹配空白字符(空格、换行等)[abc]匹配 a、b 或 c[^abc]匹配非 a、b、c 的字符1.3.3.常用方法RegExp.prototype.test()检查字符串是否匹配正则表达式。const regex = /Hello/; console.log(regex.test('Hello, World!')); // true console.log(regex.test('HELLO')); // false未匹配 大小写RegExp.prototype.exec()执行搜索匹配,返回匹配结果或 null。const regex = /Hello/; const result = regex.exec('Hello, World!'); console.log(result); // ['Hello', index: 0, input: 'Hello, World!', groups: undefined]match()在字符串中执行搜索匹配,返回匹配结果数组或 null。const str = 'Hello, World!'; console.log(str.match(/Hello/)); // ['Hello', index: 0, input: 'Hello, World!', groups: undefined]matchAll()返回所有匹配项的迭代器。const str = 'Hello, Hello!'; const regex = /Hello/g; console.log(Array.from(str.matchAll(regex))); // [['Hello', index: 0], ['Hello', index: 7]]search()返回第一个匹配项的索引。const str = 'Hello, World!'; console.log(str.search(/World/)); // 7replace()替换字符串中的匹配项。const str = 'Hello, World!'; console.log(str.replace(/World/, 'Alice')); // 'Hello, Alice!'split()将字符串拆分为数组。const str = 'Hello, World!'; console.log(str.split(/, /)); // ['Hello', 'World!']1.3.4.进阶使用捕获组与非捕获组// 捕获组(可通过 `exec` 或 `matchAll` 获取分组内容) const regex = /(a)(b)/; const str = "ab"; const result = regex.exec(str); console.log(result[1]); // "a"(第一个捕获组) console.log(result[2]); // "b"(第二个捕获组) // 非捕获组(仅分组不捕获) const regex2 = /(?:a)(b)/;前瞻(Lookahead)与后顾(Lookbehind)也叫预查断言// 正向前瞻:匹配后面跟着特定字符的内容 const str = "apple123"; console.log(str.match(/\d+(?=\.)/)); // null(无小数点) console.log("apple123.45".match(/\d+(?=\.)/)); // "123" // 反向前瞻:匹配前面是特定字符的内容 console.log("apple123".match(/(?<=apple)\d+/)); // "123" // 正向后顾:匹配前面是特定字符的内容 console.log("apple123".match(/(?<=apple)\d+/)); // "123"贪婪与非贪婪匹配const str = "<div>Hello</div><div>World</div>"; // 贪婪匹配(默认) console.log(str.match(/<div>.*<\/div>/)); // "<div>Hello</div><div>World</div>" // 非贪婪匹配(添加 ?) console.log(str.match(/<div>.*?<\/div>/g)); // ["<div>Hello</div>", "<div>World</div>"]数据提取const text = "Price: $19.99, Quantity: 5"; // 提取价格 const priceMatch = text.match(/\$\d+\.\d+/); console.log(priceMatch[0]); // "$19.99" // 提取所有数字 const numbers = text.match(/\d+/g); console.log(numbers); // ["19", "99", "5"] //提取URL const url = 'https://example.com?name=Alice&age=30'; const params = url.split('?')[1].split('&').reduce((acc, param) => { const [key, value] = param.split('='); acc[key] = value; return acc; }, {}); console.log(params); // { name: 'Alice', age: '30' }文本替换const str = "Hello WORLD"; // 替换所有大写字母为小写 const newStr = str.replace(/[A-Z]/g, (match) => match.toLowerCase()); console.log(newStr); // "hello world"1.3.5.常用正则表达式场景正则表达式说明邮箱验证^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$基础邮箱验证(允许字母、数字、点、下划线、百分号、加号、减号)。 ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$更严格验证(限制域名长度为 2~6 位)。手机号验证(中国)^1[3-9]\d{9}$验证中国大陆手机号(11 位,第二位为 3-9)。 `^(13[0-9]14[5-9]URL 验证^(https?:\/\/)?([\w.-]+)\.([a-z]{2,})(:\d+)?(\/.*)?$支持 HTTP/HTTPS 协议、域名、端口和路径。 ^https?:\/\/(www\.)?[\w-]+\.[a-z]{2,}(\/.*)?$更简洁的 URL 验证(强制包含 www.)。密码强度验证^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$必须包含大小写字母、数字、特殊字符,长度 ≥8。 ^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z\d]{8,}$简化版(至少字母和数字,长度 ≥8)。提取 HTML 标签内容<(\w+)>(.*?)<\/\1>匹配简单标签内容(如 <div>Hello</div>)。 <([a-z]+)([^<]+)*(?:>(.*)<\/\1>)?更通用的标签匹配(支持属性和嵌套内容)。提取 URL 参数[?&]([^=#]+)=([^&#]*)提取查询字符串中的键值对(如 name=Alice&age=30)。 (?<=[?&])([^=&]+)=([^&]*)使用正向后顾匹配参数键值对。隐藏手机号中间四位(\d{3})\d{4}(\d{4})将手机号中间四位替换为星号(如 138****8000)。 (\d{3})\d{3}\d{4}另一种替换方式(如 138-***-8000)。千分位分隔符(?<!\d)(?=(\d{3})+(?!\d))在数字中添加千分位逗号(如 1234567 → 1,234,567)。 /\B(?=(\d{3})+(?!\d))/g另一种实现方式(避免前导零问题)。日期格式化(YYYY-MM-DD → YYYYMMDD)(\d{4})-(\d{2})-(\d{2})移除日期中的短横线(如 2023-10-05 → 20231005)。 `\d{4}(0[1-9]1[0-2])(0[1-9]移除 HTML 标签<[^>]+>删除所有 HTML 标签(如 <p>Hello</p> → Hello)。 <\/?[a-z][\w-]*[^>]*>更全面的标签匹配(支持属性和自闭合标签)。中文标点转英文标点[,。!?;:“”‘’()《》]替换常见中文标点为英文标点(如 ,→ ,)。 [^\x00-\x7F]匹配所有非 ASCII 字符(包括中文标点)。提取所有数字\d+匹配字符串中的连续数字(如 abc123def456 → ["123", "456"])。 \b\d+\b匹配独立数字(避免匹配日期中的数字如 2023-10-05 中的 2023)。验证身份证号(18位)^\d{15}(\d{2}[0-9xX])?$验证 15 位或 18 位身份证号(最后一位可为 X/x)。 `^[1-9]\d{5}(?:1920)\d{2}(?:0[1-9]2.对象操作2.1.对象的创建2.1.1. 对象字面量(Literal)最简洁的创建方式,直接用 {} 定义键值对:const obj = { name: 'dengke', age: 18, sayHi: () => console.log('Hello!'), };2.1.2. Object 构造函数通过 new Object() 创建对象:const obj = new Object(); obj.name = '孙悟空'; // 动态添加属性2.1.3. Object.create()指定原型链创建对象:const prototypeObj = { greet: () => 'Hello' }; const obj = Object.create(prototypeObj); // obj 的原型是 prototypeObj console.log(obj.greet()); // "Hello"2.1.4. 展开运算符(Spread)浅拷贝对象或合并对象:const obj1 = { a: 1 }; const obj2 = { b: 2 }; const merged = { ...obj1, ...obj2 }; // { a:1, b:2 }2.1.5.类实例化class Person { constructor(name, age){ this.name = name; this.age = age; } } const zs = new Person("zangsan",18); // Person {name:"zangsan".age:18}2.2.对象属性操作2.2.1. 增删改查添加/修改属性:obj.newProp = 'value'; // 点语法 obj['dynamicKey'] = 100; // 方括号语法(适合动态键名)删除属性:delete obj.newProp; // 返回布尔值,成功删除返回 true访问属性:console.log(obj.name); // 点语法 console.log(obj['age']); // 方括号语法2.2.2. 特殊键名的访问数字或特殊符号键名必须用方括号语法:const obj = { '1-key': 'value', '-abc': 100 }; console.log(obj['1-key']); // "value"2.3.对象遍历2.3.1. for...in 循环遍历对象自身和继承的可枚举属性:for (const key in obj) { if (obj.hasOwnProperty(key)) { // 过滤原型链属性 console.log(key, obj[key]); } }2.3.2. Object.keys() / Object.values() / Object.entries()Object.keys():返回对象自身可枚举属性的键数组:const keys = Object.keys(obj); // ["name", "age"]Object.values():返回属性值的数组:const values = Object.values(obj); // ["dengke", 18]Object.entries():返回键值对数组:const entries = Object.entries(obj); // [["name", "dengke"], ["age", 18]]2.3.3. Reflect.ownKeys()返回对象自身所有属性(包括不可枚举和符号键):const allKeys = Reflect.ownKeys(obj); // 包含所有属性2.4.对象属性描述符2.4.1. Object.defineProperty()定义或修改单个属性的描述符:const obj = {}; Object.defineProperty(obj, 'name', { value: 'dengke', // 属性值 writable: false, // 是否可修改(默认 false) enumerable: true, // 是否可枚举(默认 false) configurable: false // 是否可删除或修改描述符(默认 false) });2.4.2. Object.defineProperties()批量定义多个属性:Object.defineProperties(obj, { age: { value: 18, writable: true }, gender: { value: 'male', configurable: false } });2.4.3. 属性类型数据属性:直接存储值(如 name)。访问器属性:通过get和set方法控制访问:Object.defineProperty(obj, 'fullName', { get() { return `${this.firstName} ${this.lastName}`; }, set(val) { [this.firstName, this.lastName] = val.split(' '); } });2.5.对象冻结与密封2.5.1. Object.freeze()冻结对象,使其不可修改、不可扩展、不可配置:const obj = { a: 1 }; Object.freeze(obj); obj.a = 2; // 无效,对象被冻结2.5.2. Object.seal()密封对象,禁止添加新属性,但允许修改现有属性值:Object.seal(obj); obj.b = 3; // 无效,无法添加新属性 obj.a = 2; // 允许修改现有属性2.5.3. Object.preventExtensions()仅阻止添加新属性,其他操作仍允许:Object.preventExtensions(obj); obj.b = 4; // 无效2.5.4. 检查对象状态Object.isExtensible(obj); // 是否可扩展 Object.getOwnPropertyDescriptor(obj, 'a'); // 获取属性描述符2.6.对象合并与扩展2.6.1. Object.assign()合并对象,浅拷贝源对象到目标对象:const target = { a: 1 }; const source = { b: 2, a: 3 }; const result = Object.assign(target, source); console.log(result); // { a:3, b:2 }(目标对象被修改)2.6.2. 展开运算符(Spread)与 Object.assign() 类似,但语法更简洁:const merged = { ...target, ...source };2.7.Reflect API(ES6+)2.7.1. 常用方法Reflect.get() / Reflect.set():Reflect.get(obj, 'name'); // 等价于 obj.name Reflect.set(obj, 'age', 20); // 等价于 obj.age = 20Reflect.deleteProperty():Reflect.deleteProperty(obj, 'name'); // 等价于 delete obj.nameReflect.construct():const Person = function(name) { this.name = name; }; const instance = Reflect.construct(Person, ['dengke']);Reflect.has():Reflect.has(obj, 'name'); // 等价于 'name' in obj2.8.对象拷贝2.8.1.浅拷贝浅拷贝是指只拷贝对象的第一层属性,而嵌套对象的引用仍然指向原始对象。如果原始对象中的嵌套对象被修改,浅拷贝后的对象也会受到影响。Object.assign()const obj1 = { a: 1, b: { c: 2 } }; const obj2 = Object.assign({}, obj1); console.log(obj2); // { a: 1, b: { c: 2 } } obj1.b.c = 3; console.log(obj2.b.c); // 3 (浅拷贝的嵌套对象引用被修改)展开运算符 (...)const obj1 = { a: 1, b: { c: 2 } }; const obj2 = { ...obj1 }; console.log(obj2); // { a: 1, b: { c: 2 } } obj1.b.c = 3; console.log(obj2.b.c); // 3 (同样受影响)2.8.2.深拷贝JSON.parse() 和 JSON.stringify()const obj1 = { a: 1, b: { c: 2 } }; const obj2 = JSON.parse(JSON.stringify(obj1)); console.log(obj2); // { a: 1, b: { c: 2 } } obj1.b.c = 3; console.log(obj2.b.c); // 2 (深拷贝后的对象不受影响)局限性:无法处理函数、undefined、Date、Map、Set 等特殊对象。无法处理循环引用(会导致栈溢出)。递归实现深拷贝function deepClone(obj, hash = new WeakMap()) { if (obj === null) return null; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (typeof obj !== 'object') return obj; if (hash.has(obj)) return hash.get(obj); const result = Array.isArray(obj) ? [] : {}; hash.set(obj, result); for (const key in obj) { if (obj.hasOwnProperty(key)) { result[key] = deepClone(obj[key], hash); } } return result; } const obj1 = { a: 1, b: { c: 2 }, d: [3, 4] }; const obj2 = deepClone(obj1); obj1.b.c = 3; console.log(obj2.b.c); // 2 (完全独立)优点:可以处理复杂对象(如 Date、Map、Set 等)。支持循环引用。使用库(如 Lodash 的 _.cloneDeep())const _ = require('lodash'); const obj1 = { a: 1, b: { c: 2 } }; const obj2 = _.cloneDeep(obj1); obj1.b.c = 3; console.log(obj2.b.c); // 2 (完全独立)2.9.常见陷阱与注意事项浅拷贝问题:Object.assign()和展开运算符仅复制对象的引用,修改嵌套对象会同步到源对象:const obj1 = { a: { b: 1 } }; const obj2 = { ...obj1 }; obj2.a.b = 2; // obj1.a.b 同样变为 2delete 操作符的限制:无法删除不可配置(configurable: false)的属性。for...in 的陷阱:会遍历原型链属性,需结合hasOwnProperty()过滤:for (const key in obj) { if (obj.hasOwnProperty(key)) { // 处理自身属性 } }Object.is() 的特殊比较:与 === 不同,Object.is(-0, 0) 返回 false,而 NaN === NaN 返回 true。3.数组操作3.1.数组的创建3.1.1. 字面量方式直接用 [] 定义数组:const arr = [1, 'apple', true];3.1.2. Array 构造函数通过 new Array() 创建:const arr1 = new Array(3); // 创建长度为3的空数组 [empty × 3] const arr2 = Array.of(1, 2, 3); // 推荐,避免构造函数的陷阱3.1.3. 填充数组const arr = Array(3).fill(0); // [0, 0, 0]3.2. 添加元素push()作用:向数组末尾添加一个或多个元素,并返回数组的新长度。示例:const arr = [1, 2, 3]; arr.push(4); // arr => [1, 2, 3, 4]unshift()作用:向数组开头添加一个或多个元素,并返回数组的新长度。示例:const arr = [1, 2, 3]; arr.unshift(0); // arr => [0, 1, 2, 3]splice()作用:向数组指定位置插入元素。语法:arr.splice(index, 0, element1, element2, ...)。示例:const arr = [1, 2, 3]; arr.splice(1, 0, 'a', 'b'); // arr => [1, 'a', 'b', 2, 3]3.3. 删除元素pop()作用:删除数组末尾的元素,并返回被删除的元素。示例:const arr = [1, 2, 3]; arr.pop(); // arr => [1, 2], 返回 3shift()作用:删除数组开头的元素,并返回被删除的元素。示例:const arr = [1, 2, 3]; arr.shift(); // arr => [2, 3], 返回 1splice()作用:删除数组指定位置的元素。语法:arr.splice(index, deleteCount)。示例:const arr = [1, 2, 3, 4, 5]; arr.splice(2, 1); // arr => [1, 2, 4, 5], 返回 [3]3.4. 查找元素indexOf()作用:查找元素在数组中的位置,返回第一个匹配的索引,未找到返回 -1。示例:const arr = [1, 2, 3, 2]; arr.indexOf(2); // 返回 1lastIndexOf()作用:从数组末尾开始查找元素,返回最后一个匹配的索引,未找到返回 -1。示例:const arr = [1, 2, 3, 2]; arr.lastIndexOf(2); // 返回 3find()作用:查找数组中第一个满足条件的元素,返回该元素。示例:const arr = [1, 2, 3, 4]; arr.find(item => item > 2); // 返回 3findIndex()作用:查找数组中第一个满足条件的元素的索引,未找到返回 -1。示例:const arr = [1, 2, 3, 4]; arr.findIndex(item => item > 2); // 返回 2findLast() / findLastIndex()作用:查找最后一个符合条件的元素:示例:const arr = [1, 2, 3, 2]; arr.findLastIndex(x => x === 2); // 3 const arr = [1, 2, 3, 2]; arr.findLast(x => x > 2); //33.5.修改元素直接赋值作用:直接修改数组中指定索引的元素。示例:const arr = [1, 2, 3]; arr[1] = 'a'; // arr => [1, 'a', 3]splice()作用:删除并插入新元素,实现替换功能。语法:arr.splice(index, deleteCount, element1, element2, ...)。示例:const arr = [1, 2, 3, 4, 5]; arr.splice(2, 1, 'a'); // arr => [1, 2, 'a', 4, 5]copyWithin作用:将数组的一部分复制到同一数组中的另一个位置,覆盖现有值。语法:array.copyWithin(target, start, end)示例:const array1 = ["a", "b", "c", "d", "e"]; console.log(array1.copyWithin(0, 3, 4)); // ["d", "b", "c", "d", "e"] console.log(array1.copyWithin(1, 3)); // ["d", "d", "e", "d", "e"]3.6. 遍历与转换map()作用:对数组中的每个元素执行函数,并返回一个新数组。示例:const arr = [1, 2, 3]; const newArr = arr.map(item => item * 2); // newArr => [2, 4, 6]filter()作用:过滤数组中的元素,返回满足条件的新数组。示例:const arr = [1, 2, 3, 4]; const newArr = arr.filter(item => item % 2 === 0); // newArr => [2, 4]forEach()作用:遍历数组中的每个元素,执行指定函数。示例:const arr = [1, 2, 3]; arr.forEach(item => console.log(item)); // 输出 1, 2, 3entries作用:返回一个包含数组中每个索引的键值对的迭代器。语法:array.entries()示例:const arr = ['a', 'b', 'c']; for (const [index, value] of arr.entries()) { console.log(index, value); } // 0 'a' // 1 'b' // 2 'c'reduce()作用:对数组中的元素进行累积操作,返回累积结果。语法:arr.reduce(callback(accumulator, currentValue), initialValue)。示例:const arr = [1, 2, 3, 4]; const sum = arr.reduce((acc, curr) => acc + curr, 0); // sum => 10flat作用:创建一个新的数组,并根据指定深度递归地将所有子数组元素拼接到新的数组中。语法:arr.flat([depth])示例:const arr1 = [0, 1, 2, [3, 4]]; console.log(arr1.flat()); // [0, 1, 2, 3, 4] const arr2 = [0, 1, [2, [3, [4, 5]]]]; console.log(arr2.flat(2)); // [0, 1, 2, 3, Array [4, 5]] console.log(arr2.flat(Infinity)); // [0, 1, 2, 3, 4, 5]flatMap()作用:结合了 map 和 flat 的功能,先对数组中的每个元素执行映射函数,然后将结果数组拍平一层。语法:arr.flatMap(callback(currentValue[, index[, array]])[, thisArg])示例:const nested = [[1], [2], [3]]; const flat = nested.flatMap(arr => arr); // [1,2,3] const arr = [1, 2, 3]; const result = arr.flatMap(x => [x, x * 2]); console.log(result); // [1, 2, 2, 4, 3, 6]3.6. 排序sort()作用:对数组进行排序,默认按字符串顺序排序。示例:const arr = [3, 1, 4, 2]; arr.sort(); // arr => [1, 2, 3, 4] (注意:默认按字符串排序)按数值排序:const arr = [3, 1, 4, 2]; arr.sort((a, b) => a - b); // arr => [1, 2, 3, 4]3.7. 合并与分割concat()作用:合并两个或多个数组,返回新数组。示例:const arr1 = [1, 2]; const arr2 = [3, 4]; const newArr = arr1.concat(arr2); // newArr => [1, 2, 3, 4]slice()作用:提取数组的一部分,返回新数组,不修改原数组。语法:arr.slice(start, end)(end 不包含)。示例:const arr = [1, 2, 3, 4]; const newArr = arr.slice(1, 3); // newArr => [2, 3]split()(字符串转数组)作用:将字符串分割为数组。示例:const str = 'a,b,c'; const arr = str.split(','); // arr => ['a', 'b', 'c']join()(数组转字符串)作用:将数组元素连接为字符串。示例:const arr = ['a', 'b', 'c']; const str = arr.join('-'); // str => 'a-b-c'3.8. 判断数组isArray()作用:判断一个对象是否为数组。示例:Array.isArray([1, 2, 3]); // true Array.isArray({}); // false3.9. 其他常用方法includes()作用:判断数组是否包含某个值,返回布尔值。示例:const arr = [1, 2, 3]; arr.includes(2); // truereverse()作用:反转数组。示例:const arr = [1, 2, 3]; arr.reverse(); // arr => [3, 2, 1]every()作用:判断数组中所有元素是否满足条件。示例:const arr = [2, 4, 6]; arr.every(item => item % 2 === 0); // truesome()作用:判断数组中是否存在至少一个满足条件的元素。示例:const arr = [1, 2, 3]; arr.some(item => item % 2 === 0); // true解构赋值const [first, second, ...rest] = [1,2,3,4]; console.log(first); // 1 console.log(rest); // [3,4]3.10.数组拷贝3.10.1. 浅拷贝slice()作用:创建一个新数组,包含原数组的元素(从开始索引到结束索引,但不包括结束索引)。语法:arr.slice([start], [end])示例:const arr = [1, 2, 3, 4]; const shallowCopy = arr.slice(); console.log(shallowCopy); // [1, 2, 3, 4]局限性:只拷贝第一层,嵌套对象的引用仍然共享。展开运算符 (...)作用:将数组展开为新数组。语法:const newArr = [...arr]示例:const arr = [1, 2, 3, 4]; const shallowCopy = [...arr]; console.log(shallowCopy); // [1, 2, 3, 4]局限性:同样只拷贝第一层。concat()作用:合并数组并返回新数组。语法:arr.concat()示例:const arr = [1, 2, 3, 4]; const shallowCopy = arr.concat(); console.log(shallowCopy); // [1, 2, 3, 4]局限性:只拷贝第一层。3.10.2. 深拷贝JSON.parse(JSON.stringify())作用:将数组转换为 JSON 字符串,再解析为新数组。语法:JSON.parse(JSON.stringify(arr))示例:const arr = [1, 2, { a: 3 }, [4, 5]]; const deepCopy = JSON.parse(JSON.stringify(arr)); console.log(deepCopy); // [1, 2, { a: 3 }, [4, 5]]局限性:无法处理函数、undefined、Date、Map、Set 等特殊对象。无法处理循环引用。递归实现深拷贝作用:手动递归拷贝数组及其嵌套元素。实现:function deepClone(obj, hash = new WeakMap()) { if (obj === null) return null; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (typeof obj !== 'object') return obj; if (hash.has(obj)) return hash.get(obj); const result = Array.isArray(obj) ? [] : {}; hash.set(obj, result); for (const key in obj) { if (obj.hasOwnProperty(key)) { result[key] = deepClone(obj[key], hash); } } return result; } const arr = [1, 2, { a: 3 }, [4, 5]]; const deepCopy = deepClone(arr); console.log(deepCopy); // [1, 2, { a: 3 }, [4, 5]]优点:支持复杂对象和循环引用。缺点:实现复杂,性能较差。Lodash 的 _.cloneDeep()作用:使用 Lodash 库实现深拷贝。语法:_.cloneDeep(arr)示例:const _ = require('lodash'); const arr = [1, 2, { a: 3 }, [4, 5]]; const deepCopy = _.cloneDeep(arr); console.log(deepCopy); // [1, 2, { a: 3 }, [4, 5]]优点:功能强大,支持复杂对象和循环引用,性能较好。缺点:需要引入外部库。structuredClone()作用:使用现代浏览器的 structuredClone API。语法:structuredClone(arr)示例:const arr = [1, 2, { a: 3 }, [4, 5]]; const deepCopy = structuredClone(arr); console.log(deepCopy); // [1, 2, { a: 3 }, [4, 5]]优点:简单易用,支持多种数据类型,性能较好。缺点:不支持函数、Symbol 等某些特殊类型,浏览器兼容性有限。3.11.数组去重使用 Set:const arr = [1, 2, 2, 3, 4, 4, 5]; const uniqueArr = [...new Set(arr)]; console.log(uniqueArr); // [1, 2, 3, 4, 5]使用 filter 和 indexOf:const arr = [1, 2, 2, 3, 4, 4, 5]; const uniqueArr = arr.filter((item, index, self) => self.indexOf(item) === index); console.log(uniqueArr); // [1, 2, 3, 4, 5]使用 reduce:const arr = [1, 2, 2, 3, 4, 4, 5]; const uniqueArr = arr.reduce((acc, item) => { if (!acc.includes(item)) { acc.push(item); } return acc; }, []); console.log(uniqueArr); // [1, 2, 3, 4, 5]3.12性能优化注意事项push 和 pop:O(1) 时间复杂度,效率高。unshift 和 shift:O(n) 时间复杂度,效率较低,尽量避免在大数据量时使用。splice:性能取决于删除/插入的位置和数量,尽量避免频繁使用。map 和 filter:遍历整个数组,复杂度为 O(n),适合中小规模数据。修改方法:push, pop, shift, unshift, splice, reverse, sort 会改变原数组。安全方法:map, filter, slice, concat 返回新数组。sort() 的默认行为:默认按字符串排序,需传入比较函数进行数值或自定义排序。slice() 和展开运算符 ([...arr]) 仅拷贝一层,嵌套对象仍为引用。4.高阶函数4.1.定义高阶函数指:接收函数作为参数(如 map、filter)。// 示例:回调函数 function repeat(n, callback) { for (let i = 0; i < n; i++) { callback(i); } } repeat(3, (index) => console.log(`Iteration ${index}`)); // 输出:Iteration 0, Iteration 1, Iteration 2返回函数作为结果(如柯里化、闭包)。// 示例:闭包 function createCounter() { let count = 0; return function() { return count++; }; } const counter = createCounter(); console.log(counter()); // 0 console.log(counter()); // 1或两者兼具。4.2.高阶函数用法4.2.1 柯里化将多参数函数转换为单参数函数链:function curryAdd(a) { return function(b) { return a + b; }; } const add5 = curryAdd(5); console.log(add5(3)); // 84.2.2函数组合组合多个函数为一个函数:function compose(f, g) { return function(x) { return f(g(x)); }; } const uppercase = str => str.toUpperCase(); const reverse = str => str.split('').reverse().join(''); const reverseUpper = compose(uppercase, reverse); console.log(reverseUpper("hello")); // "OLLEH"4.2.3.装饰器模式动态增强函数功能:function logger(fn) { return function(...args) { console.log("Calling function with", args); const result = fn.apply(this, args); console.log("Result:", result); return result; }; } const add = logger((a, b) => a + b); add(2, 3); // 输出日志并返回54.3.闭包闭包(Closure) 是一个函数与其词法作用域(Lexical Environment) 的组合。它允许函数访问并操作其外部函数的变量,即使外部函数已经执行完毕。4.3.1.工作原理词法作用域与执行上下文词法作用域:函数的作用域由其定义的位置决定。例如:function outer() { const outerVar = '外层变量'; function inner() { console.log(outerVar); // 引用外层变量 } return inner; } const closure = outer(); closure(); // 输出:外层变量inner 函数在定义时“记住”了 outer 的作用域,即使 outer 已执行完毕,inner 仍能访问 outerVar。词法环境(Lexical Environment)词法环境由两部分组成:环境记录(Environment Record):存储变量、函数声明等。外层环境引用(Outer Environment Reference):指向父级作用域。闭包的持久化:当外部函数执行完毕后,如果内部函数被外部引用,其词法环境不会被垃圾回收机制释放,从而形成闭包。垃圾回收机制JavaScript 的垃圾回收机制会回收不再被引用的变量和对象。闭包的内存问题:如果闭包引用了大量外部变量且长期存在,可能导致内存泄漏。4.3.2.应用场景数据封装与私有变量模拟私有变量:function Counter() { let count = 0; // 私有变量 return { increment: () => count++, get: () => count }; } const counter = Counter(); console.log(counter.get()); // 0 counter.increment(); console.log(counter.get()); // 1count 是外部函数 Counter 的局部变量,通过闭包被内部方法访问,外部无法直接修改。保存状态(持续化变量)计数器示例:function createCounter() { let count = 0; return () => count++; } const counter = createCounter(); console.log(counter()); // 0 console.log(counter()); // 1count 的值在每次调用时被保留,形成“持续状态”。回调函数与异步编程异步操作中保存上下文:function asyncTask(data) { setTimeout(() => { console.log(`处理数据: ${data}`); }, 1000); } asyncTask("Hello"); // 1秒后输出 "处理数据: Hello"setTimeout 的回调函数通过闭包访问了外部函数 asyncTask 的参数 data。5.解构操作5.1.数组结构基本用法const arr = [1, 2, 3]; const [a, b, c] = arr; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3跳过元素//你可以通过在解构模式中留空来跳过数组中的某些元素。 const arr = [1, 2, 3, 4, 5]; const [a, , b, , c] = arr; console.log(a); // 1 console.log(b); // 3 console.log(c); // 5默认值//如果数组中的某些元素不存在,你可以为变量提供默认值。 const arr = [1, 2]; const [a, b, c = 3] = arr; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3嵌套解构const arr = [1, [2, 3], 4]; const [a, [b, c], d] = arr; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3 console.log(d); // 4剩余参数const [head, ...tail] = [1, 2, 3, 4]; console.log(head); // 1 console.log(tail); // [2, 3, 4]5.2.对象解构基本用法const obj = { a: 1, b: 2, c: 3 }; const { a, b, c } = obj; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3重命名变量你可以为解构的属性指定不同的变量名。const obj = { a: 1, b: 2 }; const { a: x, b: y } = obj; console.log(x); // 1 console.log(y); // 2默认值如果对象中没有某个属性,你可以为变量提供默认值。const obj = { a: 1 }; const { a, b = 2 } = obj; console.log(a); // 1 console.log(b); // 2嵌套解构对象解构支持嵌套结构。const obj = { a: 1, b: { c: 2, d: 3 }, e: 4 }; const { a, b: { c, d }, e } = obj; console.log(a); // 1 console.log(c); // 2 console.log(d); // 3 console.log(e); // 4剩余参数const { id, ...rest } = { id: 1, name: 'Bob', age: 25 }; console.log(rest); // { name: 'Bob', age: 25 }5.3.函数参数解构// 对象解构 function printUser({ name, age }) { console.log(`Name: ${name}, Age: ${age}`); } printUser({ name: 'Alice', age: 30 }); // Name: Alice, Age: 30// 数组解构function sum([a, b]) { return a + b;}console.log(sum([1, 2])); // 3 #### 5.4.复杂嵌套结构 const data = { user: {name: "Bob", address: { city: "New York" }}, hobbies: ["reading", "coding"]};// 解构嵌套对象const { user: { name, address: { city } }, hobbies: [firstHobby, ...otherHobbies]} = data;console.log(name, city); // "Bob" "New York"console.log(firstHobby, otherHobbies); // "reading" ["coding"] #### 5.5.应用场景 - **交换变量值** 通过解构实现变量交换: let x = 1, y = 2; [x, y] = [y, x]; // x=2, y=1 - **字符串解构** 将字符串视为字符数组进行解构: const [a, b, c] = 'cat'; // a='c', b='a', c='t' - **计算属性名** 用表达式作为属性名: const key = 'age'; const obj = { age: 25 }; const { [key]: userAge } = obj; // userAge=25 - **从函数返回多个值** function getCoordinates() {return { x: 10, y: 20 };} const { x, y } = getCoordinates(); console.log(x, y); // 10 20 - **忽略不需要的值** const [onlyFirst, , third] = [1, 2, 3]; console.log(onlyFirst, third); // 1 3 - **解构与模块导入** // mathUtils.js export const add = (a, b) => a + b; export const subtract = (a, b) => a - b;// main.js import { add, subtract } from "./mathUtils.js"; console.log(add(5, 3)); // 8 ### 6.JSON操作 #### 6.1.`JSON.stringify()` 将对象或数组转为字符串,支持过滤、转换和格式化。 - 语法:`JSON.stringify(value[, replacer[, space]])` - **`value`**: 要序列化的对象。 - **`replacer`**(可选):函数或数组,用于过滤或转换属性。 - **`space`**(可选):格式化缩进(数字或字符串)。 - 示例 const obj = { name: "Alice", age: 25, date: new Date() };// 基础序列化 console.log(JSON.stringify(obj)); // '{"name":"Alice","age":25,"date":"2023-10-01T00:00:00.000Z"}'// 过滤属性(仅保留 name 和 age) console.log(JSON.stringify(obj, ["name", "age"])); // '{"name":"Alice","age":25}'// 使用 replacer 函数 console.log(JSON.stringify(obj, (key, value) => {if (key === "date") return value.toISOString(); // 格式化日期 return value;}));//用于指定缩进空格数,使输出的 JSON 字符串更易读。 const obj = { name: 'Alice', age: 30 }; const jsonString = JSON.stringify(obj, null, 2); console.log(jsonString); // { // "name": "Alice", // "age": 30 // } - 循环引用问题:默认无法处理循环引用,会导致错误。可以通过 `replacer` 函数来处理。 const obj = { a: 1 }; obj.b = obj;try {JSON.stringify(obj); // 抛出错误} catch (e) {console.error('Error:', e.message);}// 使用 replacer 处理循环引用 function replacer(key, value) {if (value === obj) return '[Circular]'; return value;}console.log(JSON.stringify(obj, replacer)); // '{"a":1,"b":"[Circular]"}' - **`JSON.stringify()` 会忽略函数、undefined和 `Symbol` 键**: const obj = {name: 'Alice', greet: function() { console.log('Hello!'); }, id: Symbol('123')}; console.log(JSON.stringify(obj)); // '{"name":"Alice"}' #### 6.2.`JSON.parse()` 将 JSON 字符串转换为 JavaScript 对象或数组。 - **语法**:`JSON.parse(text[, reviver])` - **`text`**:要解析的 JSON 字符串。 - **`reviver`**(可选):函数,用于在解析后转换结果(如类型转换或数据校验)。 - 示例 const jsonString = '{"name":"Alice","age":30}'; const obj = JSON.parse(jsonString); console.log(obj); // { name: 'Alice', age: 30 }//reviver const jsonString = '{"name":"Alice","age":30,"email":"alice@example.com"}'; const obj = JSON.parse(jsonString, (key, value) => {if (key === 'email') return value.toUpperCase(); return value;}); console.log(obj); // { name: 'Alice', age: 30, email: 'ALICE@EXAMPLE.COM' }//如果 JSON 字符串格式不正确,JSON.parse() 会抛出错误。 const invalidJson = '{"name": "Alice",}'; // 额外的逗号 try {JSON.parse(invalidJson);} catch (e) {console.error('Error:', e.message); // Error: Unexpected token } at position 15} ### 7.集合 #### 7.1.Map 用于键值对存储,键可以是任何数据类型(包括对象、函数等)。保持插入顺序。 ##### 7.1.1.方法 | 方法 | 功能描述 | | -------------------- | ------------------------------------------------ | | `new Map()` | 创建一个空的 `Map`。 | | `.set(key, value)` | 设置键值对,若键存在则更新值,返回 `Map` 本身。 | | `.get(key)` | 获取指定键的值,若不存在返回 `undefined`。 | | `.has(key)` | 检查是否存在指定键。 | | `.delete(key)` | 删除指定键的键值对,返回是否删除成功。 | | `.clear()` | 清空所有键值对。 | | `.keys()` | 返回一个包含所有键的迭代器。 | | `.values()` | 返回一个包含所有值的迭代器。 | | `.entries()` | 返回一个包含 `[key, value]` 数组的迭代器。 | | `.forEach(callback)` | 遍历所有键值对,回调参数为 `(value, key, map)`。 | **示例** const map = new Map([ ["name", "Alice"], [42, "The Answer"]]);// 添加/删除元素map.set("age", 25); // Map(3) { "name" → "Alice", 42 → "The Answer", "age" → 25 }map.delete("name"); // true → 移除键 "name"// 查询与遍历map.get(42); // "The Answer"map.has("age"); // truemap.size; // 2// 遍历map.forEach((value, key) => console.log(${key}: ${value}));//使用对象const user = { id: 1 };const userMap = new Map();userMap.set(user, "Alice"); // 键是对象console.log(userMap.get(user)); // "Alice"//动态的键值对const cache = new Map();cache.set("key1", "value1");cache.set(123, { data: "test" });// 对象转 Mapconst obj = { a: 1, b: 2 };const mapFromObj = new Map(Object.entries(obj)); // Map { "a" → 1, "b" → 2 }// Map 转对象const objFromMap = Object.fromEntries(mapFromObj); // { a: 1, b: 2 }//Map转数组const arr = Array.from(map); ##### 7.1.2.和Object比较 | 特性 | `Map` | 对象(Object) | | -------- | ---------------------------- | ----------------------------------- | | 键的类型 | 任意类型(包括对象、函数等) | 仅字符串或符号(Symbol) | | 遍历顺序 | 保持插入顺序 | 无保证(ES5 及之前) | | 大小查询 | `map.size` | 需手动统计或 `Object.keys().length` | | 性能 | 更适合频繁增删改的场景 | 适合简单的键值存储 | #### 7.2.Set 集合(Set)是一种数据结构,用于存储唯一的值。集合中的元素是唯一的,这意味着集合中不能有重复的值。集合提供了多种方法来添加、删除和检查元素。 ##### 7.2.1.基本方法 | 方法 | 功能描述 | | -------------------- | ---------------------------------------------------------- | | `new Set()` | 创建一个空的 `Set`。 | | `.add(value)` | 向集合中添加一个元素,若已存在则不操作,返回 `Set` 本身。 | | `.delete(value)` | 从集合中删除指定元素,返回是否删除成功(`true`/`false`)。 | | `.has(value)` | 检查集合中是否存在指定元素,返回布尔值。 | | `.clear()` | 清空集合中的所有元素。 | | `.size` | 返回集合中元素的数量。 | | `.forEach(callback)` | 遍历集合中的每个元素,执行回调函数。也可以用`for...of` | | `.values()` | 返回一个包含集合中所有值的迭代器。 | // 通过数组初始化const fruits = new Set(["apple", "banana", "cherry"]);// 逐步添加元素const numbers = new Set();numbers.add(1).add(2).add(3); // 链式调用// 通过变量添加元素const name = "Alice";const users = new Set();users.add(name); // 添加字符串users.add({ id: 1 }); // 添加对象//遍历const mySet = new Set([1, 2, 3]);for (const value of mySet) { console.log(value);}// 1// 2// 3const mySet = new Set([1, 2, 3]);mySet.forEach(value => { console.log(value);});// 1// 2// 3//集合转数组const mySet = new Set([1, 2, 3]);const arr = Array.from(mySet); // 或 [...mySet]console.log(arr); // [1, 2, 3] - **`NaN`**:虽然 `NaN !== NaN`,但 `Set` 中只会存储一个 `NaN`。 - **`null`/`undefined`**:会被视为唯一值,但多次添加不会重复。 ##### 7.2.2.高级方法 - **`union()`**:合并两个 `Set`,去重后返回新 `Set`。 - **`intersection()`**:返回两个 `Set` 的交集。 - **`difference()`**:返回在第一个 `Set` 中但不在第二个中的元素。 - **`symmetricDifference()`**:返回两个 `Set` 的非交集元素。 const setA = new Set([1, 2, 3]);const setB = new Set([3, 4, 5]);// 合并const unionSet = setA.union(setB); // {1, 2, 3, 4, 5}// 交集const intersectionSet = setA.intersection(setB); // {3}// 差集const differenceSet = setA.difference(setB); // {1, 2}// 对称差集const symDiffSet = setA.symmetricDifference(setB); // {1, 2, 4, 5} ##### 7.2.3.应用 - **去重与统计频率** const arr = [1, 2, 2, 3, 3, 3]; const frequency = [...new Set(arr)].reduce((acc, num) => {acc[num] = arr.filter(x => x === num).length; return acc;}, {}); // {1:1, 2:2, 3:3} ### 8.日期处理 #### 8.1. 创建日期对象 - **当前日期和时间**: const now = new Date(); console.log(now); // 当前日期和时间 - **指定日期和时间**: const specificDate = new Date(2023, 9, 15, 12, 30, 0); // 年, 月(0-11), 日, 时, 分, 秒 console.log(specificDate); // 2023-10-15T12:30:00 - **日期字符串**: const dateString = new Date('2023-10-15T12:30:00'); console.log(dateString); // 2023-10-15T12:30:00 #### 8.2. 获取日期和时间 - **获取年份**: const year = new Date().getFullYear(); console.log(year); // 2023 - **获取月份**(0-11): const month = new Date().getMonth(); console.log(month); // 9 (十月) - **获取日期**: const day = new Date().getDate(); console.log(day); // 15 - **获取星期几**(0-6,0 表示星期日): const dayOfWeek = new Date().getDay(); console.log(dayOfWeek); // 0-6 - **获取小时**: const hours = new Date().getHours(); console.log(hours); // 0-23 - **获取分钟**: const minutes = new Date().getMinutes(); console.log(minutes); // 0-59 - **获取秒数**: const seconds = new Date().getSeconds(); console.log(seconds); // 0-59 - **获取毫秒**: const milliseconds = new Date().getMilliseconds(); console.log(milliseconds); // 0-999 #### 3. 设置日期和时间 - **设置年份**: const date = new Date(); date.setFullYear(2024); console.log(date.getFullYear()); // 2024 - **设置月份**: const date = new Date(); date.setMonth(11); // 11 表示 12 月 console.log(date.getMonth()); // 11 - **设置日期**: const date = new Date(); date.setDate(20); console.log(date.getDate()); // 20 - **设置小时**: const date = new Date(); date.setHours(15); console.log(date.getHours()); // 15 - **设置分钟**: const date = new Date(); date.setMinutes(30); console.log(date.getMinutes()); // 30 - **设置秒数**: const date = new Date(); date.setSeconds(45); console.log(date.getSeconds()); // 45 - **设置毫秒**: const date = new Date(); date.setMilliseconds(500); console.log(date.getMilliseconds()); // 500 #### 8.4. 日期格式化 - **使用 `toLocaleDateString()`**: const date = new Date(); console.log(date.toLocaleDateString()); // 2023/10/15 (格式取决于浏览器的本地设置) - **自定义格式化**: function formatDate(date) {const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`;}const date = new Date(); console.log(formatDate(date)); // 2023-10-15 - **使用 `Intl.DateTimeFormat`(推荐)** const date = new Date(); const options = {year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'Asia/Shanghai' // 指定时区}; console.log(new Intl.DateTimeFormat('zh-CN', options).format(date)); // "2023/12/25 10:30:00" - **使用第三方库(如 `date-fns`)** import { format } from 'date-fns'; import { zhCN } from 'date-fns/locale';console.log(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: zhCN })); // "2023-12-25 10:30:00"8.5. 日期计算计算两个日期之间的天数差:function daysBetween(date1, date2) { const diffTime = Math.abs(date2 - date1); return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); } const date1 = new Date('2023-10-01'); const date2 = new Date('2023-10-15'); console.log(daysBetween(date1, date2)); // 14添加天数到日期:function addDays(date, days) { const newDate = new Date(date); newDate.setDate(newDate.getDate() + days); return newDate; } const date = new Date('2023-10-15'); const newDate = addDays(date, 5); console.log(newDate); // 2023-10-20时间戳const now = new Date(); const timestamp = now.getTime(); // 获取当前时间戳(毫秒) console.log(timestamp); // 例如:1712023102000 // 通过Date.now()快速获取时间戳 console.log(Date.now()); // 等同于new Date().getTime()8.6. 时区处理获取 UTC 时间:const date = new Date(); console.log(date.toUTCString()); // Wed, 18 Oct 2023 04:30:00 GMT获取本地时间:const date = new Date(); console.log(date.toLocaleString()); // 2023/10/15 下午12:30:00 (格式取决于浏览器的本地设置)10.事件10.1.Event对象用户或浏览器触发的交互行为(如点击、键盘输入、页面加载等)。事件处理函数的参数 event 包含交互的详细信息:常用属性属性描述event.type事件类型(如 "click")。event.target触发事件的实际元素(原始目标)。event.currentTarget当前处理事件的元素(绑定监听器的元素)。event.preventDefault()阻止默认行为(如表单提交、链接跳转)。event.stopPropagation()阻止事件冒泡/捕获。event.clientX/Y鼠标事件的坐标(相对于视口)。示例代码:button.addEventListener("click", (event) => { console.log("目标元素:", event.target); // 实际点击的元素 console.log("当前元素:", event.currentTarget); // 绑定事件的元素 event.preventDefault(); // 阻止默认行为(如表单提交) event.stopPropagation(); // 阻止事件冒泡 });10.2.事件传播机制事件传播分为三个阶段:捕获阶段(Capture Phase):事件从 window 向下传递到目标元素。目标阶段(Target Phase):事件到达目标元素。冒泡阶段(Bubble Phase):事件从目标元素向上传递回 window。示例:点击嵌套元素 div > p 时的事件流顺序:window → document → html → body → div → p(捕获阶段) p → div → body → html → document → window(冒泡阶段)事件委托:利用事件冒泡机制,将事件监听器绑定到父元素,处理子元素的事件:<ul id="parent"> <li>Item 1</li> <li>Item 2</li> </ul>const parent = document.getElementById("parent"); parent.addEventListener("click", (event) => { if (event.target.tagName === "LI") { console.log("列表项被点击:", event.target.textContent); } });10.3.自定义事件// 创建自定义事件 const customEvent = new CustomEvent("myEvent", { detail: { message: "Hello!" }, }); // 触发事件 document.dispatchEvent(customEvent); // 监听自定义事件 document.addEventListener("myEvent", (event) => { console.log("自定义事件触发:", event.detail.message); });10.4.常用事件事件类别事件名称触发时机备注用户界面事件click鼠标点击元素时触发最常用事件之一 dblclick双击元素时触发注意防止双击选中文本 contextmenu右键点击元素时触发(默认弹出右键菜单)可用 event.preventDefault() 阻止默认行为 mousedown鼠标按下时触发常用于拖拽功能 mouseup鼠标释放时触发与 mousedown 配合使用焦点事件focus元素获得焦点时触发(如输入框点击、激活)不冒泡 blur元素失去焦点时触发不冒泡 focusin元素获得焦点时触发(支持冒泡)可用于事件委托 focusout元素失去焦点时触发(支持冒泡)同上鼠标事件mouseover鼠标进入元素或其子元素时触发会冒泡 mouseout鼠标离开元素或其子元素时触发会冒泡 mouseenter鼠标进入元素时触发(不检测子元素)不冒泡 mouseleave鼠标离开元素时触发(不检测子元素)不冒泡 mousemove鼠标在元素上移动时触发高频触发,需注意性能键盘事件keydown按下键盘按键时触发(字符键和功能键)可获取 event.key 或 event.keyCode keypress按下字符键时触发(已废弃,推荐用 keydown) keyup松开键盘按键时触发 表单事件submit表单提交时触发(如点击提交按钮)可阻止默认提交行为 change表单元素值改变且失去焦点时触发(如输入框、下拉框)常用于实时验证 input表单元素值改变时立即触发(无需失去焦点)实时性更强 reset表单重置时触发 窗口事件resize浏览器窗口大小改变时触发需节流处理高频触发 scroll页面或元素滚动时触发需优化性能 load页面或图片等资源完全加载完成时触发常用于 window 或 <img> unload页面卸载时触发(如关闭标签页)不推荐使用,存在兼容性问题拖放事件dragstart拖拽操作开始时触发需设置元素为 draggable="true" dragover拖拽元素在目标元素上方移动时触发需调用 event.preventDefault() drop拖拽元素在目标元素上释放时触发 剪贴板事件copy复制操作时触发可修改剪贴板内容 cut剪切操作时触发 paste粘贴操作时触发 资源加载事件error资源加载失败时触发(如图片、脚本) 触摸事件touchstart手指触摸屏幕时触发移动端常用 touchmove手指在屏幕上滑动时触发需调用 event.preventDefault() 防止页面滚动 touchend手指离开屏幕时触发 11.BOM11.1.Window对象代表浏览器窗口(全局对象)常用属性location:访问当前窗口的 Location 对象。history:访问当前窗口的 History 对象。navigator:访问当前浏览器的 Navigator 对象。screen:访问当前屏幕的 Screen 对象。document:访问当前窗口的文档对象(DOM 根对象)。innerWidth/innerHeight:获取窗口内部宽度/高度(包含滚动条)。outerWidth/outerHeight:获取窗口外部宽度/高度(包含浏览器边框和工具栏)。常用方法方法名说明示例alert()显示警告对话框window.alert("提示信息");confirm()显示确认对话框(返回布尔值)if (window.confirm("确定提交?")) { ... }prompt()显示输入对话框(返回输入值或 null)let input = window.prompt("请输入");setTimeout()设置定时器,延迟执行代码setTimeout(() => { console.log("执行"); }, 1000);setInterval()设置周期性定时器setInterval(() => { console.log("每秒执行"); }, 1000);clearTimeout()/clearInterval()清除定时器clearTimeout(timerId);open()打开新窗口或标签页window.open("https://example.com");close()关闭当前或指定窗口window.close();resizeTo()调整窗口大小window.resizeTo(800, 600);moveTo()移动窗口到指定坐标window.moveTo(100, 100);scrollTo()/scrollBy()滚动页面到指定位置window.scrollTo(0, document.body.scrollHeight);11.2.Navigator对象浏览器对象属性描述navigator.appName获取浏览器的名称navigator.appVersion获取浏览器的平台和版本信息navigator.language获取当前浏览器的语言navigator.userAgent获取用户代理字符串navigator.cookieEnabled获取浏览器是否启用cookienavigator.onLine获取浏览器是否处于在线模式navigator.platform获取运行浏览器的操作系统平台方法名说明geolocation.getCurrentPosition()获取用户地理位置vibrate()触发设备振动(需权限)sendBeacon()异步发送小数据到服务器11.3.Location浏览器的地址栏信息属性名说明href完整 URL(如 https://example.com/path?query#hash)protocolURL 的协议(如 https:)host主机名 + 端口号(如 example.com:8080)hostname主机名(如 example.com)port端口号(如 8080)pathname路径部分(如 /path)search查询字符串(如 ?key=value)hash锚点部分(如 #section)origin协议、主机和端口的组合(如 https://example.com)searchParamsURL 查询参数的 URLSearchParams 对象(ES6+)常用方法方法名说明assign(url)加载新 URL(替换当前历史记录)replace(url)替换当前页面且不生成历史记录reload()重新加载当前页面11.4.History属性描述history.length返回历史浏览记录的当前长度方法说明back()返回上一页(等同于浏览器的后退按钮)forward()前进到下一页go(n)跳转到指定历史记录索引(0 为当前页,-1 为上一页)pushState(state, title, url)无刷新添加历史记录条目(SPA 常用)replaceState(state, title, url)替换当前历史记录条目(无刷新)11.5.screen属性名说明availWidth屏幕可用宽度(排除任务栏)availHeight屏幕可用高度(排除任务栏)width屏幕总宽度(含任务栏)height屏幕总高度(含任务栏)colorDepth屏幕颜色深度(位数)11.6.Document方法描述示例代码getElementById(id)根据元素的 ID 获取元素。const element = document.getElementById('myId');querySelector(selector)使用 CSS 选择器获取第一个匹配的元素。const element = document.querySelector('#myId');querySelectorAll(selector)使用 CSS 选择器获取所有匹配的元素,返回一个静态节点列表。const elements = document.querySelectorAll('.myClass');getElementsByClassName(name)根据类名获取元素,返回一个 HTML 集合。const elements = document.getElementsByClassName('myClass');getElementsByTagName(name)根据标签名获取元素,返回一个 HTML 集合。const elements = document.getElementsByTagName('div');createElement(tagName)创建一个新的 HTML 元素。const newElement = document.createElement('div');createTextNode(text)创建一个新的文本节点。const textNode = document.createTextNode('Hello, World!');appendChild(node)将一个节点添加到父节点的子节点列表的末尾。parentElement.appendChild(newElement);insertBefore(node, referenceNode)在参考节点之前插入一个节点。parentElement.insertBefore(newElement, referenceNode);removeChild(node)从父节点中移除一个子节点。parentElement.removeChild(childElement);replaceChild(newNode, oldNode)用新节点替换旧节点。parentElement.replaceChild(newNode, oldNode);addEventListener(type, listener)为元素添加事件监听器。element.addEventListener('click', function() { console.log('Clicked!'); });removeEventListener(type, listener)移除元素的事件监听器。element.removeEventListener('click', myFunction);getAttribute(name)获取元素的指定属性值。const value = element.getAttribute('href');setAttribute(name, value)设置元素的指定属性值。element.setAttribute('href', 'https://example.com');removeAttribute(name)移除元素的指定属性。element.removeAttribute('href');innerHTML获取或设置元素的 HTML 内容。element.innerHTML = '<p>New content</p>';textContent获取或设置元素的文本内容(不解析 HTML)。element.textContent = 'New text';style获取或设置元素的样式。element.style.color = 'red';classList操作元素的类列表。element.classList.add('myClass');getComputedStyle(element)获取元素的计算样式。const style = window.getComputedStyle(element);输出流方法描述示例代码document.write()向文档写入 HTML 内容(慎用,仅在页面加载前使用)。document.write("<h1>Hello</h1>");document.writeln()写入 HTML 内容并换行。document.writeln("<div>Line 1 Line 2</div>");示例代码// 通过 ID 获取元素 const elementById = document.getElementById('myId'); // 通过类名获取元素 const elementsByClass = document.getElementsByClassName('myClass'); // 通过标签名获取元素 const elementsByTag = document.getElementsByTagName('div'); // 使用 CSS 选择器获取元素 const elementBySelector = document.querySelector('#myId'); const elementsBySelector = document.querySelectorAll('.myClass'); const href = element.getAttribute("href"); // 获取属性值 // 创建新元素 const newDiv = document.createElement('div'); newDiv.textContent = 'New content'; // 添加到文档 document.body.appendChild(newDiv); // 在指定位置插入元素 const referenceElement = document.getElementById('reference'); referenceElement.parentNode.insertBefore(newDiv, referenceElement); element.setAttribute("title", "点击查看详情"); // 设置属性 element.removeAttribute("data-old"); // 删除属性 element.checked = true; // 复选框选中状态 element.disabled = false; // 启用按钮 // 添加点击事件监听器 const button = document.getElementById('myButton'); button.addEventListener('click', function() { console.log('Button clicked!'); }); // 移除事件监听器 function handleClick() { console.log('Button clicked!'); } button.removeEventListener('click', handleClick);
2023年05月07日
132 阅读
0 评论
0 点赞
2023-05-03
【学习笔记】Javascript(一)
Javascript基础1.HelloWorld1.1<script>标签<!DOCTYPE html> <html> <body> <script type="script"> document.body.innerHTML = "<h1>Hello World</h1>"; console.log("Hello World"); </script> </body> </html>1.2.独立js文件document.body.innerHTML = "<h1>Hello World</h1>"; console.log("Hello World");<!DOCTYPE html> <html> <body> <!-- script引入外部后,内部无法再写代码,不会被浏览器解析--> <script type="text/javascript" src="./hello.js"></script> </body> </html>1.3.html标签<!DOCTYPE html> <html> <body> <button onclick="alert("Hello World")"></button> <a href="javascript:alert("Hello World")"></a> </body> </html>2.基础语法2.1语法格式严格区分大小写。语句以;·分号结尾,如果不写,浏览器会自动添加。但可能造成错误。JS会忽略多个空格和换行。引号、括号闭合。代码注释:/* 多行注释 多行注释 */ //单行注释2.2.变量声明2.2.1.示例// 使用 let 声明变量(块级作用域) let age = 25; // 使用 const 声明常量(不可重新赋值) const PI = 3.14159; // 不推荐使用 var(函数级作用域,易引发问题) var name = "Alice";2.2.2.标识符使用规则:必须以 字母(A-Z/a-z)、下划线(_) 或 美元符号($) 开头。后续字符可以是 字母、数字(0-9)、下划线或美元符号。不区分大小写(但推荐统一风格,如驼峰命名法 myVariable 或下划线分隔 my_variable)。允许使用 Unicode 转义序列(如 \uXXXX),但需谨慎使用。命名规范:语义清晰:用名称表达用途(如 userAge 而非 a)。驼峰命名法:多单词变量/函数使用小驼峰(getUserName)。常量全大写:常量名用全大写加下划线(MAX_LENGTH)。避免缩写:除非是广泛认可的缩写(如 id、URL)。禁止使用保留字(见下文)。// 合法标识符 let userName = "Alice"; const _privateVar = 10; function calculateTotal() {} // 非法标识符(会报错) let 2ndPlace = "Silver"; // 以数字开头 const class = "Math"; // 使用保留字严格保留字(Strict Mode Reserved Words)在代码中添加 'use strict'; 后,以下关键字禁止使用:关键字用途implements接口实现(ECMAScript 6+)interface接口定义let块级作用域变量声明private类私有字段(实验性)public类公共字段(实验性)static类静态方法/属性yield生成器函数关键字await异步函数关键字2. 未来保留字(Future Reserved Words)目前可用,但未来可能成为保留字,建议避免使用:关键字用途enum枚举类型(ECMAScript 6+ 提案)await异步函数关键字(已部分实现)implements接口实现(ECMAScript 6+)3. 其他保留字以下关键字已在标准中明确定义,不可用作标识符:关键字用途break循环/switch 跳出caseswitch 分支catch异常捕获class类定义const常量声明continue循环继续debugger调试断点defaultswitch 默认分支、模块默认导出delete删除对象属性dodo...while 循环elseif 条件分支export模块导出extends类继承finallytry...catch 最终执行块forfor 循环function函数声明if条件判断import模块导入in成员检测、循环遍历instanceof类型检测let块级变量声明new对象实例化return函数返回值super类父级引用switch多分支选择this当前上下文对象throw抛出异常try异常处理typeof类型检测var函数级变量声明void返回无值whilewhile 循环with对象作用域扩展(不推荐使用2.2.3.var、let和const区别ES5(2009年):引入 var 作为唯一的变量声明关键字。ES6(2015年):新增 let 和 const,引入块级作用域,逐步取代 var。特性varletconst作用域函数作用域(Function Scope)块级作用域(Block Scope)块级作用域(Block Scope)变量提升提升到函数或全局顶部不提升(存在暂时性死区)不提升(存在暂时性死区)重复声明允许禁止禁止重新赋值允许允许禁止(声明时必须初始化)内存分配动态分配(可修改)动态分配(可修改)静态分配(不可修改)作用域var:作用域为最近的函数或全局范围。function test() { if (true) { var x = 10; } console.log(x); // 输出 10(x 在函数内有效) }let/const:作用域为最近的代码块({})。function test() { if (true) { let y = 20; const z = 30; } console.log(y); // 报错(y 未定义) console.log(z); // 报错(z 未定义) }变量提升(Hoisting)var:变量声明会被提升到顶部,但赋值不会。console.log(a); // undefined(声明被提升) var a = 5;let/const:存在“暂时性死区”(Temporal Dead Zone, TDZ),声明前无法访问。console.log(b); // ReferenceError(TDZ) let b = 10;重复声明var:允许重复声明同一个变量。var c = 1; var c = 2; // 合法但危险 let/const:禁止重复声明。let d = 1; let d = 2; // SyntaxError重新赋值var/let:允许重新赋值。let e = 5; e = 10; // 合法const:声明时必须初始化,且不可重新赋值。const f = 10; f = 20; // TypeError3.数据类型类型示例说明数字let num = 10;整数、浮点数均可,不区分类型。字符串let str = "Hello";单引号、双引号或反引号包裹。布尔值let isTrue = true;true 或 false。数组let arr = [1, "a", true];用 [] 定义,元素类型可不同。对象let obj = { name: "Bob" };键值对集合,用 {} 定义。null/undefinedlet n = null; let u;null 表示空值,undefined 表示未定义。3.1.数值let num = 103.1.1.Number所有数字(包括整数和浮点数)均以 64 位双精度浮点数 存储。格式:符号位(1位) + 指数(11位) + 尾数(52位)。范围:安全整数范围:-(2^53 - 1) 到 2^53 - 1(即 -9007199254740991 到 9007199254740991)。最大/最小值:Number.MAX_VALUE = 1.7976931348623157e+308; // 最大正数 Number.MIN_VALUE = 5e-324; // 最小正数 const a = 9007199254740991; // 安全最大值 const b = a + 1; // 可能不精确 console.log(b === a + 1); // false(超出安全范围)精度问题超过安全整数范围时,连续整数可能无法精确表示。console.log(0.1 + 0.2); // 输出 0.30000000000000004 // 解决方案: console.log((0.1 + 0.2).toFixed(2)); // "0.30"(保留两位小数)浮点数运算可能产生舍入误差(如 0.1 + 0.2 !== 0.3)。3.1.2.特殊值值描述检测方法NaN非数字(Not-a-Number),如 0/0 或 parseInt("abc")。isNaN(value)(全局)或 Number.isNaN(value)(ES6 更精确)Infinity正无穷大(如 1 / 0)。value === Infinity-Infinity负无穷大(如 -1 / 0)。value === -Infinity-0负零(与 0 在大多数运算中等价,但可通过 Object.is() 区分)。Object.is(-0, 0) → falseMath 对象常用方法:Math.random(); // 生成 [0, 1) 的随机数 Math.floor(3.7); // 向下取整 → 3 Math.ceil(3.2); // 向上取整 → 4 Math.round(3.5); // 四舍五入 → 4 Math.max(1, 5, 3); // 最大值 → 5 Math.min(-1, -5, 0); // 最小值 → -5// 数学运算 console.log(Math.sqrt(16)); // 4 console.log(Math.pow(2, 3)); // 8 // 特殊值处理 console.log(isNaN(NaN)); // true(全局 isNaN) console.log(Number.isNaN(NaN)); // true(ES6 更精确) // 精度问题 console.log(0.1 + 0.2); // 0.30000000000000004 console.log((0.1 + 0.2).toFixed(2)); // "0.30"3.1.5.Bigint值:用 n 后缀表示的大整数(如 100n)。特点:解决 Number 的精度问题(如超过 2^53 的整数)。与 Number 类型不兼容,需显式转换。示例:const big = 9007199254740991n + 1n; // 9007199254740992n console.log(big + 1); // 报错,需用 big + 1n3.2.字符串3.2.1.定义字符串一旦创建,内容不可修改。所有操作会生成新字符串:const str1 = "Hello World"; // 双引号 const str2 = 'Hello World'; // 单引号 const str3 = `Hello World`; // 反引号(模板字符串)可以跨行 const str4 = `Hello World ${str3}`;//嵌入变量 let s = "abc"; s[0] = "x"; // 无效,严格模式下会报错 console.log(s); // 输出 "abc" s = "def"; //生成新字符串3.2.2.常用操作拼接与重复const name = "Alice"; const greeting = "Hello, " + name + "!"; // 模板字符串更推荐 console.log(greeting); // 输出 "Hello, Alice!" // 重复字符串 console.log("abc".repeat(3)); // "abcabcabc"截取与拼接const text = "JavaScript is awesome!"; console.log(text.slice(0, 10)); // "JavaScript"(左闭右开) console.log(text.substring(0, 10)); // 同 slice console.log(text.split(" ")); // ["JavaScript", "is", "awesome!"]查找与替换const str = "Hello, World!"; console.log(str.indexOf("World")); // 7(返回起始索引) console.log(str.includes("World")); // true(ES6+) // 替换 console.log(str.replace("World", "JS")); // "Hello, JS!" console.log(str.replaceAll("l", "L")); // "HeLLo, WorLD!"(ES2021+)大小写转换const str = "Hello World!"; console.log(str.toUpperCase()); // "HELLO WORLD!" console.log(str.toLowerCase()); // "hello world!"字符串遍历const str = "abc"; for (let char of str) { // 使用 for...of 遍历字符 console.log(char); }字符串填充console.log("5".padStart(3, "0")); // "005"(左侧填充) console.log("5".padEnd(3, "0")); // "500"(右侧填充)字符串截取进阶const text = "Hello World!"; console.log(text.startsWith("Hello")); // true console.log(text.endsWith("!")); // true console.log(text.includes("World")); // true3.2.3字符串转义转义序列作用示例\"双引号(")"他说:\"你好!\""\'单引号(')'他说:\'你好!\''\\反斜杠(\)"路径:C:\\Users\\"`换行符`"第一行第二行"` \t制表符(Tab)"列1\t列2"\r回车符(Carriage Return)`"Windows 换行:\r"` \b退格符"删除前一个字符\b"\f换页符"分页符\f"3.3.布尔值以下值在逻辑判断中会被视为 false:值类型说明false布尔值逻辑假0数字零""字符串空字符串null对象主动置空undefinedundefined未定义NaN数字非数字//`0`、`-0`、`NaN`、`""`(空字符串)、`null`、`undefined` 转换为 `false` console.log(Boolean(0)); // false(Falsy 值) console.log(Boolean("")); // false console.log(Boolean([])); // true(对象始终为 Truthy) console.log(Boolean({})); // true if (0) { /* 不会执行 */ } if ("") { /* 不会执行 */ }3.4.空值3.4.1.undefined含义:表示变量已声明但未赋值,或函数未返回值。常见场景:let name; // 声明未赋值 → name 的值为 undefined function foo() {} // 无返回值 → foo() 返回 undefined检测方法:console.log(typeof name); // "undefined" console.log(name === undefined); // true3.4.2.null含义:表示主动赋值的“空”或“无”,通常用于明确清空值。常见场景:let user = { name: "Alice" }; user = null; // 主动置空检测方法:console.log(user === null); // true console.log(typeof null); // "object"(历史遗留问题,需注意)3.4.3.对比型检测方法典型场景undefinedvalue === undefined变量未声明或函数无返回值nullvalue === null主动置空或明确表示“无”空字符串str.length === 0输入框未填写空数组arr.length === 0数据列表初始状态空对象Object.keys(obj).length === 0配置对象未初始化3.4.4.空值处理检查 null 或 undefinedconst value = null; if (value == null) { // 等价于 (value === null || value === undefined) console.log("值为 null 或 undefined"); }默认值设置const name = inputName || "匿名"; // 如果 inputName 是假值,则用 "匿名" const age = parseInt(inputAge) ?? 0; // 空值或 NaN 时用 0(ES2020+)安全访问深层对象const user = { profile: { address: null } }; // 避免报错:user.profile.address.city → 可能抛出错误 const city = user?.profile?.address?.city ?? "未知"; // 使用可选链和空值合并3.5.Symbol3.5.1.定义用于创建 唯一且不可变的标识符。基础创建const sym1 = Symbol(); // 无描述的 Symbol const sym2 = Symbol("description"); // 带描述的 Symbol全局 Symbol 注册表通过 Symbol.for() 创建全局共享的 Symbol,可通过 Symbol.keyFor() 查找:const globalSym = Symbol.for("sharedKey"); console.log(Symbol.keyFor(globalSym)); // "sharedKey"特性:唯一性每个 Symbol 值都是全局唯一的,即使描述相同,两个 Symbol 也不相等:const sym1 = Symbol("key"); const sym2 = Symbol("key"); console.log(sym1 === sym2); // false不可变性Symbol 的描述(description)不可修改,且一旦创建无法销毁。原始类型Symbol 是原始类型,不能通过 new 关键字实例化:const sym = Symbol(); // 正确 // const sym = new Symbol(); // 报错3.5.2.内置常量JavaScript 提供了一些内置的 Symbol 常量,用于定义语言行为:Symbol 常量用途Symbol.iterator定义对象的默认迭代器Symbol.toStringTag自定义对象的 toString() 结果(如 "[object MyType]")Symbol.hasInstance定义 instanceof 操作符的行为Symbol.unscopables控制 with 语句中哪些属性不可访问Symbol.species指定构造函数创建实例时的替代构造函数3.5.3.应用场景对象属性的唯一键避免对象属性名冲突(尤其适用于第三方库或多人协作项目):const user = { [Symbol("id")]: 123, name: "Alice" }; console.log(user[Symbol("id")]); // undefined(不同 Symbol 实例) const PLUGIN_SYM = Symbol("plugin");定义私有属性结合闭包或 WeakMap 实现私有字段:const privateData = new WeakMap(); class User { constructor(name) { privateData.set(this, { name }); } getName() { return privateData.get(this).name; } }迭代器协议通过 Symbol.iterator 定义对象的默认迭代行为:const iterable = { [Symbol.iterator]() { let step = 0; return { next: () => ({ value: step++, done: step > 2 }) }; } }; for (const value of iterable) { console.log(value); // 0, 1, 2 }自定义 toStringTag通过 Symbol.toStringTag 定制对象的 toString() 结果:class MyClass { get [Symbol.toStringTag]() { return "MyClass"; } } console.log(new MyClass().toString()); // "[object MyClass]"3.5.4.常见问题Symbol 与字符串的混淆const sym = Symbol("key"); console.log(typeof sym); // "symbol"(不是字符串) console.log(sym.toString()); // "Symbol(key)"无法直接序列化Symbol 无法被 JSON 序列化:const obj = { [Symbol("id")]: 123 }; console.log(JSON.stringify(obj)); // "{}"作为对象键的限制Symbol 作为对象键时,无法通过常规方式枚举:const obj = { [Symbol("id")]: 123, name: "Alice" }; console.log(Object.keys(obj)); // ["name"](Symbol 键被忽略) console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(id)]3.6.类型转换3.6.1转换为布尔值隐式转换:Falsy 值(自动转为 false):false、0、""(空字符串)、null、undefined、NaN。Truthy 值(自动转为 true):非空字符串(如 "0"、" ")非零数字(如 1、-1)数组(如 [])对象(如 {})函数(如 function() {})if ("0") { console.log("Truthy"); } // 输出(字符串非空) if (0) { console.log("Falsy"); } // 不输出(0 是 falsy) if ([]) { console.log("Truthy"); } // 输出(数组是对象)主动调用:方法说明示例Boolean(value)强制转换为布尔值Boolean(0) → false!!value双重否定转换!!0 → falseconsole.log(Boolean(0)); // false console.log(Boolean("")); // false console.log(Boolean(null)); // false console.log(Boolean(undefined)); // false console.log(Boolean(NaN)); // false console.log(Boolean([])); // true(空数组是对象,对象为 Truthy) console.log(Boolean({})); // true(空对象也是 Truthy) console.log(!!0); // false console.log(!!"hello"); // true console.log(!![]); // true console.log(!!{}); // true3.6.2.转换为字符串方法说明示例String(value)强制转换为字符串String(123) → "123"value.toString()对象调用 toString() 方法(123).toString() → "123"${value}模板字符串转换`${123} → "123"`//String() console.log(String(123)); // "123" console.log(String(true)); // "true" console.log(String(null)); // "null" console.log(String(undefined)); // "undefined" console.log(String(Symbol("id"))); // "Symbol(id)" //toString console.log((123).toString()); // "123" console.log(true.toString()); // "true" console.log((NaN).toString()); // "NaN" console.log({}.toString()); // "[object Object]" //${} const num = 456; console.log(`Value: ${num}`); // "Value: 456" console.log(String(NaN)); // "NaN" console.log(String(Infinity)); // "Infinity" console.log(String(undefined)); // "undefined" console.log(String(null)); // "null"隐式转换:字符串拼接console.log("Number: " + 123); // "Number: 123" console.log("Boolean: " + true); // "Boolean: true"模板字符串插值:const obj = { name: "Alice" }; console.log(`User: ${obj}`); // "User: [object Object]"alert() 或 prompt():alert(123); // 显示 "123"3.6.3.转换为数值转换为 Number方法描述示例Number(value)强制转换(严格转换,非数字返回 NaN)。Number("123") → 123parseInt(string)解析字符串为整数(可指定进制)。parseInt("10.5") → 10parseFloat(string)解析字符串为浮点数。parseFloat("3.14") → 3.14+value一元加号转换(隐式转换)。+"123" → 123console.log(Number("")); // 0 console.log(Number(" ")); // 0 console.log(Number(true)); // 1 console.log(Number(false)); // 0 console.log(Number(null)); // 0 console.log(Number(undefined)); // NaN console.log(Number("123")); // 123 // parseInt console.log(parseInt("123.45")); // 123(截断小数) console.log(parseInt("12a3", 10)); // 12(遇到非数字字符停止解析) //parseFloat console.log(parseFloat("12.34")); // 12.34 console.log(parseFloat("12.3.4")); // 12.3(截断到第二个小数点) //一元加号转换(隐式转换)。 console.log(+"123"); // 123 console.log(+""); // 0 console.log(+"abc"); // NaN console.log(+null); // 0 console.log(+undefined); // NaN4.运算符4.1.算术运算符运算符说明示例结果+加法5 + 38-减法10 - 46*乘法2 * 3.57/触发10 / 33.333...(浮点数)%取模10 % 31**幂运算2 ** 38(指数运算)console.log(5 + 3); // 8(数字相加) console.log("5" + 3); // "53"(字符串拼接) console.log([1, 2] + { a: 3 }); // "1,2[object Object]"(类型转换后拼接) console.log("5" + 3 + 2); // "532"(字符串拼接优先级高于加法) console.log(5 + 3 + "2"); // "82"(先数字相加,再拼接) console.log(9007199254740991 + 1); // 9007199254740992(超过安全整数范围) console.log(10 - 4); // 6 console.log("10" - 4); // 6(字符串转数字) console.log("10a" - 4); // NaN(无法转换) console.log(10 / 0); // Infinity console.log(-10 / 0); // -Infinity console.log(3 * 4); // 12 console.log("3" * "4"); // 12 console.log("3" * true); // 3(`true` 转为 1) console.log(10 / 2); // 5 console.log(10 / 3); // 3.333... console.log("10" / 3); // 3.333... console.log("10" / "2"); // 5 console.log(10 % 3); // 1(10 ÷ 3 = 3 余 1) console.log(-10 % 3); // -1(-10 ÷ 3 = -4 余 -1) console.log(10 % -3); // 1(余数符号与被除数一致) console.log(7 % 3); // 1 console.log(-7 % 3); // -1(余数符号与被除数一致) console.log(7 % -3); // 1(余数符号与被除数一致) console.log(2 ** 3); // 8(2 的 3 次方) console.log(10 ** -1); // 0.1(10 的 -1 次方) console.log(2 ** 0.5); // 1.414...(平方根)4.2.赋值运算符运算符示例等价表达式说明+=x += 5x = x + 5加法后赋值-=x -= 3x = x - 3减法后赋值*=x *= 2x = x * 2乘法后赋值/=x /= 4x = x / 4除法后赋值%=x %= 7x = x % 7取余后赋值**=x **= 3x = x ** 3指数运算后赋值(ES7+)<<=x <<= 2x = x << 2左移后赋值>>=x >>= 1x = x >> 1算术右移后赋值>>>=x >>>= 3x = x >>> 3逻辑右移后赋值(无符号)&=x &= 0b1100x = x & 0b1100按位与后赋值^=x ^= 0b1010x = x ^ 0b1010按位异或后赋值`= ``x= 0b0011`??=x ??= 10x = x ?? 10若 x 为 null/undefined,则赋值右侧值&&=x &&= yx = x && (x = y)若 x 为真值,才赋值右侧值(需注意语法)let num = 10; num += 5; // 等价于 num = num + 5 → 15 let num = 10; num -= 3; // 等价于 num = num - 3 → 7 let num = 5; // 二进制 101 num <<= 1; // 左移一位 → 1010 (10)4.3.逻辑运算符运算符作用返回值类型短路行为&&两侧都为真时返回右侧,否则左侧原始操作数是` `两侧任意一侧为真,返回真`左侧为真时返回左侧,否则右侧!取反布尔值布尔值 (true/false)否??左侧为 null/undefined 返回右侧原始操作数否!!将任意值强制转换为布尔值:const value = "hello"; console.log(!!value); // true(非空字符串是 truthy)逻辑运算符的返回值&& 返回第一个 falsy 值或最后一个值:console.log(5 && 3); // 3(均为 truthy) console.log(0 && 3); // 0(0 是 falsy) console.log("" && null);// ""(空字符串是 falsy)|| 返回第一个 truthy 值或最后一个值:console.log(5 || 3); // 5(均为 truthy) console.log(0 || 3); // 3(0 是 falsy) console.log("" || null);// null(均为 falsy)常见用法://条件判断 const age = 20; if (age >= 18 && age < 60) { console.log("成年且未退休"); } //默认值设置 const username = inputUsername || "匿名用户"; //安全访问深层对象属性 const city = user?.profile?.address?.city ?? "未知"; //优先级 console.log(true || false && false); // true(`&&` 优先级高于 `||`) // 等价于 true || (false && false)4.4.关系运算符运算符描述示例结果>大于5 > 3true<小于3 < 5true>=大于等于5 >= 5true<=小于等于3 <= 5true==等于(弱相等,隐式转换)5 == "5"true!=不等于(弱不等)5 != "5"false===全等(严格相等)5 === "5"false!==不全等(严格不等)5 !== "5"true数值与非数值比较,会转换数值后再比较字符串比较时,比较字符的Unicode编码null和undefined相等比较返回true===比较两个值是否全等,比较两个值的类型不同时直接返回false==会先将比较内容转换为相同类型,通常转换为数值console.log(5 == "5"); // true(字符串 "5" 转换为数字 5) console.log(5 === "5"); // false(类型不同) console.log(null == undefined); // true(特殊规则) console.log(null === undefined); // false(类型不同) console.log(0 == ""); // true(0 和空字符串均转为 0) console.log("" == false); // true(空字符串和 false 均转为 0) console.log(NaN == NaN); // false(NaN 不等于任何值,包括自身) console.log(NaN === NaN); // false条件运算符条件?表达式1:表达式2let a = 200; let b = 100; a > b ? console.log(a) : console.log(b)5.if语句5.1.语法if (condition) { // 当 condition 为 true 时执行的代码 } else if { //当条件不满足的其他另一情况 } else { //当上述条件都不满足 }说明:condition:布尔表达式,结果为 true 或 false。若 condition 为 true,执行代码块;否则退出 if 语句。JavaScript 会将非布尔值隐式转换为布尔值(Truthy/Falsy)。语句块中调用return方法后,退出if语句。其他条件分支则不会执行。if (age < 18) { console.log("未成年"); return; } else if (age >= 18 && age < 60) { console.log("成年且未退休"); } else { console.log("退休"); }6.switch语句6.1.基础语法switch (expression) { case value1: // 当 expression === value1 时执行 break; case value2: // 当 expression === value2 时执行 break; default: // 当所有 case 都不匹配时执行 }说明:expression:任意表达式(变量、函数调用、计算式等)。case:匹配 expression 的值,若匹配则执行对应代码块。break:跳出 switch,防止代码继续执行后续 case(必须显式添加)。default:可选分支,当所有 case 不匹配时执行。严格相等(===):case 的值必须与 expression 严格相等。若不写 break,代码会继续执行后续 caseconst fruit = "apple"; switch (fruit) { case "apple": console.log("Red or Green?"); break; case "banana": console.log("Yellow"); break; default: console.log("Unknown fruit"); }6.2.ES6新特性直接返回值,无需 break:const day = 3; const result = switch (day) { case 1 -> "Monday"; case 2 -> "Tuesday"; case 3 -> "Wednesday"; default -> "Other day"; }; console.log(result); // "Wednesday"多个 case 合并const status = 200; switch (true) { case (status >= 200 && status < 300): console.log("Success"); break; case (status === 404): console.log("Not Found"); break; default: console.log("Error"); }7.while语句7.1.基础语法while (condition) { // 当 condition 为 true 时执行的代码块 }说明:condition:布尔表达式,每次循环开始时检查。若为 true,执行循环体;否则退出循环。循环体:缩进的代码块,可包含任意语句。执行流程:1.检查条件 → 2.条件为 true 则执行循环体 → 3.重复步骤 1,直到条件为 false。死循环:while(true){}7.2.do...while会先执行一次循环体,再检查条件,至少执行一次:let count = 0; do { console.log("至少执行一次:", count); count++; } while (count < 3); // 输出:0,1,27.3.循环控制continue:跳过当前循环的剩余代码,进入下一次循环:let i = 0; while (i < 5) { i++; if (i === 3) continue; // 跳过 i=3 if (i === 5) break; // 当 i=5 时退出 console.log("Skipped:", i); } // 输出:1,2,4break:立即跳出当前循环。let num = 0; while (num < 10) { num++; if (num === 5) break; // 当 num=5 时退出循环 if (num === 8) break; // 当 num=8 时退出循环 console.log("Current value:", num); } // 输出:1,2,3,4嵌套循环的控制outer: while (true) { inner: while (true) { break outer; // 直接退出外层循环 } }8.for循环8.1.基础语法for (initialization; condition; iteration) { // 循环体 }说明:initialization:循环变量的初始化(仅在循环开始前执行一次)。condition:布尔表达式,每次循环开始前检查。若为 true,执行循环体;否则退出循环。iteration:迭代表达式,每次循环结束后执行(通常用于更新变量)。三个表达式都可以省略。执行流程:1.初始化变量 → 2. 检查条件 → 3. 条件为 true 则执行循环体 → 4. 执行迭代表达式 → 重复步骤 2。for (let i = 0; i < 5; i++) { console.log(i); // 输出 0, 1, 2, 3, 4 } //死循环 for (;;) {} 嵌套:for (let i = 0; i < 3; i++) { for (let j = 0; j < 2; j++) { console.log(`i=${i}, j=${j}`); } } // 输出:i=0,j=0 → i=0,j=1 → i=1,j=0 → ... 8.2.ES6新特性for...of遍历可迭代对象(如数组、字符串、Map 等):const arr = [1, 2, 3]; for (const value of arr) { console.log(value); // 输出 1, 2, 3 } const str = "hello"; for (const char of str) { console.log(char); // 输出 h, e, l, l, o }for...in遍历对象的可枚举属性(包括原型链属性):const obj = { a: 1, b: 2 }; for (const key in obj) { console.log(key); // 输出 "a", "b" }循环控制同while9.对象9.1.定义对象字面量const person = { name: "Alice", age: 25, greet() { console.log(`Hi, I'm ${this.name}`); } };构造函数function Person(name, age) { this.name = name; this.age = age; this.greet = function() { console.log(`Hi, I'm ${this.name}`); }; } const alice = new Person("Alice", 25);Object.create()const proto = { greet() { console.log("Hello!"); } }; const obj = Object.create(proto); obj.greet(); // 输出 "Hello!"ES6 Class 语法class Person { constructor(name, age) { this.name = name; this.age = age; } greet() { console.log(`Hi, I'm ${this.name}`); } } const bob = new Person("Bob", 30);9.2.常用操作属性访问与修改console.log(person.name); // "Alice" person.age = 26; // 修改属性 person["address"] = "New York"; // 动态添加属性计算属性名(ES6)const key = "email"; const user = { [key]: "alice@example.com" }; console.log(user.email); // "alice@example.com"删除属性delete person.age; // 移除 age 属性对象遍历for...in 循环for (const key in person) { if (person.hasOwnProperty(key)) { // 过滤原型链属性 console.log(`${key}: ${person[key]}`); } }Object.keys() / values() / entries()console.log(Object.keys(person)); // ["name", "greet"] console.log(Object.values(person)); // ["Alice", greet 函数] console.log(Object.entries(person)); // [["name", "Alice"], ["greet", ƒ]]for...of 与迭代器const obj = { [Symbol.iterator]() { let step = 0; return { next: () => ({ value: step++, done: step > 2 }) }; } }; for (const value of obj) { console.log(value); // 0, 1, 2 }9.3.Window对象Window 对象是浏览器中的全局对象,代表当前浏览器窗口或标签页。它是 JavaScript 运行环境的核心,所有全局变量、函数和对象均属于 Window 对象的属性和方法。9.3.1.属性属性描述window.navigator提供浏览器信息(如名称、版本、操作系统等)window.location获取或设置当前 URL,支持跳转、刷新等操作window.history管理浏览历史记录(前进、后退、跳转)window.screen获取屏幕信息(分辨率、颜色深度等)window.document代表当前页面的文档对象(DOM 树的入口)window.frames获取所有子框架(<iframe>)的集合window.parent获取当前窗口的父窗口(若为 <iframe>)console.log(window.navigator.userAgent); // 浏览器用户代理字符串 console.log(window.location.href); // 当前页面 URL const element = window.document.getElementById("myElement");9.3.2.方法方法描述setTimeout(fn, ms)延迟执行函数 fn,超时时间为 ms 毫秒setInterval(fn, ms)每隔 ms 毫秒重复执行函数 fnclearTimeout(id)清除由 setTimeout 设置的定时器clearInterval(id)清除由 setInterval 设置的定时器const timer = setTimeout(() => { console.log("延迟 2 秒执行"); }, 2000); clearTimeout(timer); // 取消定时器方法描述window.open(url)打开新窗口或标签页window.close()关闭当前窗口(仅限通过 open() 打开的窗口)window.alert(msg)显示警告对话框window.confirm(msg)显示确认对话框,返回布尔值window.prompt(msg)显示输入对话框,返回用户输入值window.open("https://www.example.com");s9.4.原型对象9.4.1.原型概念每个函数(构造函数)都有一个 prototype 属性,指向一个原型对象。通过 new 创建的实例对象的 [[Prototype]](即 __proto__)会指向构造函数的 prototype 对象。原型对象本身也是一个普通对象,可以包含属性和方法。static 方法属于类本身,不挂载到原型。普通方法挂载到原型对象。function Person(name) { this.name = name; } const p1= new Person('1'); // 原型对象 console.log(Person.prototype); // Person {} console.log(Object.getPrototypeOf(p1)) console.log(p1.__proto__);9.4.2.原型作用将一个该类实例中所有的公共属性(方法)统一存储到原型,这样只需创建一个属性,即可被所有实例访问通过修改原型链实现继承:class Student extends Person { constructor(name, grade) { super(name); this.grade = grade; } } const bob = new Student("Bob", 12); bob.sayHi(); // 继承自 Person 的方法将方法定义在原型上,避免每个实例重复创建:function Person(name) { this.name = name; } Person.prototype.sharedMethod = function() { console.log("Shared method"); }; const alice = new Person("Alice"); const bob = new Person("Bob"); console.log(alice.sharedMethod === bob.sharedMethod); // true(同一函数引用)9.4.3.原型属性查找规则当访问对象的属性时,JavaScript 引擎会:在对象自身查找。若未找到,沿 [[Prototype]] 链向上查找,直到原型链末端(null)。示例:Person.prototype.sayHi = function() { console.log(`Hi, I'm ${this.name}`); }; const alice = new Person("Alice"); alice.sayHi(); // "Hi, I'm Alice"(通过原型链找到方法)原型链的层级所有对象最终通过原型链继承自 Object.prototype。Object.prototype 的 [[Prototype]] 为 null,形成链的终点。console.log(alice.__proto__ === Person.prototype); // true console.log(Person.prototype.__proto__ === Object.prototype); // true console.log(Object.prototype.__proto__); // null9.4.4.操作原型修改原型对象通过构造函数的 prototype 属性添加方法或属性,所有实例共享这些属性。注意:直接修改 Object.prototype 会污染全局对象,应避免。// 添加方法到原型 Person.prototype.age = 30; alice.age; // 30(所有实例共享)使用 Object.create()通过 Object.create(proto) 创建一个新对象,并指定其原型:const bob = Object.create(Person.prototype); bob.name = "Bob"; bob.sayHi(); // "Hi, I'm Bob"10.函数10.1.定义函数(Function)也是一个对象创建方式:// 函数声明(函数名可复用) function greet(name) { return `Hello, ${name}!`; } // 函数表达式(匿名函数赋值给变量) const sayGoodbye = function(name) { return `Goodbye, ${name}!`; }; // 箭头函数(ES6+) const add = () => console.log(111);函数调用:function(name){ return 'Hello' + name; } console.log(greet("Alice")); // "Hello, Alice!" console.log(sayGoodbye("Bob")); // "Goodbye, Bob!" console.log(add(2, 3)); // 510.2.参数定义默认参数:如果调用方未传入参数。function greet(name = "Guest") { return `Hello, ${name}!`; } console.log(greet()); // "Hello, Guest!"剩余参数(Rest Parameters):接收可变参数function sum(...numbers) { return numbers.reduce((acc, num) => acc + num, 0); } console.log(sum(1, 2, 3, 4)); // 10解构赋值参数:function printUser({ name, age }) { console.log(`Name: ${name}, Age: ${age}`); } printUser({ name: "Alice", age: 25 }); // "Name: Alice, Age: 25"函数参数:function executeTwice(fn) { fn(); fn(); } executeTwice(() => console.log("Hello!")); // 输出两次 "Hello!"注意事项:JS不会检查参数类型,可以传递任意类型。实参多余形参,多余的实参不会使用。形参多余实参,多余的形参为undefined。箭头函数只有一个参数时,括号可以省略。function hello(name, content){ alert(`hello,${name},${content}`); } hello('sam');//hello,sam,undefined const read = content => {}10.3.返回值显式返回:使用 return 返回值。隐式返回:箭头函数若无 return,默认返回 undefined。无返回值:未使用 return 或返回 undefined。function multiply(a, b) { return a * b; // 显式返回 } const divide = (a, b) => a / b; // 隐式返回特殊情况:返回函数:function createAdder(a) { return function(b) { return a + b; }; } const add5 = createAdder(5); console.log(add5(3)); // 8箭头函数返回值:可以直接写在箭头后const sum = (a, b) => a + b //直接返回对象时,需要用()包裹 const fn = () => ({name:"sam"})10.4.作用域10.4.1.词法作用域(Lexical Scope)函数内部可以访问外部作用域的变量,但外部无法访问内部变量。const outerVar = "I am outer"; function innerFunction() { const innerVar = "I am inner"; console.log(outerVar); // 输出 "I am outer" } innerFunction(); console.log(innerVar); // 报错(innerVar 未定义)10.4.2.闭包(Closure)闭包是函数与其词法环境的组合,允许函数访问外部变量。function createCounter() { let count = 0; return function() { count++; return count; }; } const counter = createCounter(); console.log(counter()); // 1 console.log(counter()); // 2JS会优先选择当前作用域的变量进行使用let a = 1; let b = 1; { let a = 2; let sum = a + b; }10.5.立即执行函数格式:(function)()//立即执行,且只会调用一次 (function(){ let a = 10; console.log(111); }());10.6.this关键字10.6.1.普通函数默认绑定:在非严格模式下,this 默认指向全局对象(浏览器中是 window,Node.js 中是 global)。在严格模式下,this 为 undefined。function foo() { console.log(this); } foo(); // 非严格模式:window;严格模式:undefined隐式绑定:当函数作为对象的方法调用时,this 指向调用该方法的对象。const obj = { name: "Alice", sayHi() { console.log(this.name); } }; obj.sayHi(); // "Alice"显式绑定:使用 call、apply 或 bind 显式指定 this。function greet(greeting) { console.log(`${greeting}, ${this.name}`); } const user = { name: "Bob" }; greet.call(user, "Hello"); // "Hello, Bob"new 绑定:使用 new 调用构造函数时,this 指向新创建的对象。function Person(name) { this.name = name; } const alice = new Person("Alice"); console.log(alice.name); // "Alice"10.6.2.箭头函数箭头函数没有自己的 this,继承自外层作用域的 this。const obj = { value: 42, getValue: function() { console.log(this.value); }, getValueArrow: () => { console.log(this.value); // undefined(箭头函数继承全局 this) } }; obj.getValue(); // 42 obj.getValueArrow(); // undefined11.类11.1.类的定义class Person { name = ""; age = 1; // 构造函数 constructor(name, age) { this.name = name; this.age = age; } // 实例方法 greet() { console.log(`Hi, I'm ${this.name}`); } } // 创建实例 const alice = new Person("Alice", 25); alice.greet(); // "Hi, I'm Alice"11.2.属性实例属性:只能通过实例进行访问class Person { name = "lisi"; } const lisi = new Person(); lisi.name;静态属性:static 关键字定义类属性,通过类名.获取class Person { static name = "lisi"; } Person.name私有属性:外部无法直接访问的属性class Person { #name; constructor(name){ this.#name = name; } getName(){ return this.#name } }11.3.方法实例方法:通过实例对象访问class Person { read(){ console.log('read'); } } new Person().read();静态方法:通过类名访问class Person { static read(){ console.log('read'); } } Person.read();11.4.构造函数作用:初始化对象的属性。特点:每个类只能有一个构造函数,若未显式定义,会自动生成一个空构造函数。class Person { constructor(name,age){ this.name = name; this.age = age; } }11.5.封装、继承、多态封装:将属性、方法等封装为一个对象,并将他们私有化,以保护该对象数据。继承:通过 extends 关键字实现继承:class Student extends Person { constructor(name, age, grade) { super(name, age); // 调用父类构造函数 this.grade = grade; } study() { console.log(`${this.name} is studying in grade ${this.grade}`); } } const bob = new Student("Bob", 18, 12); bob.greet(); // "Hi, I'm Bob"(继承自 Person) bob.study(); // "Bob is studying in grade 12"多态:JS不会检查参数类型,调用某个函数,无需指定的类型,只需满足某些条件。11.6.InstanceOf&hasOwnPropertyinstanceOf检查一个对象是否是某个构造函数的实例(即是否存在于其原型链中)。instanceof 会沿着对象的原型链([[Prototype]])向上查找,直到找到匹配的构造函数的 prototype 属性或到达原型链末端(null)。// function Person() {} const alice = new Person(); console.log(alice instanceof Person); // true console.log(alice instanceof Object); // true(所有对象最终继承自 Object) function Animal() {} function Dog() {} Dog.prototype = Object.create(Animal.prototype); const dog = new Dog(); console.log(dog instanceof Dog); // true console.log(dog instanceof Animal); // true(原型链继承)检查对象自身(不含原型链)是否具有某个属性。const obj = { a: 1 }; console.log(obj.hasOwnProperty("a")); // true console.log(obj.hasOwnProperty("toString")); // false(继承自 Object.prototype) const parent = { inherited: "I am inherited" }; const child = Object.create(parent); child.own = "I am own"; console.log("inherited" in child); // true(原型链上的属性) console.log(child.hasOwnProperty("inherited")); // false12.数组12.1.定义// 定义数组 const arr1 = [1, 2, 3]; // 字面量 const arr2 = new Array(3); // 构造函数(长度为3的空数组) const arr3 = Array.of(1, "a"); // ES6 方法(支持混合类型) console.log(typeof arr1); // "object"(数组本质是对象) console.log(Array.isArray(arr1)); // true(判断是否为数组)特性:有序性:元素按索引(0 开始)排列。灵活性:允许混合类型元素(数字、字符串、对象等)。动态长度:可随时添加或删除元素。12.2.常用操作增删改查方法描述示例push(...items)末尾添加元素,返回新长度arr.push(4) → [1,2,3,4]pop()删除末尾元素,返回被删元素arr.pop() → 4shift()删除头部元素,返回被删元素arr.shift() → 1unshift(...items)头部添加元素,返回新长度arr.unshift(-1) → [-1,1,2]splice(start, deleteCount, ...items)插入/删除元素(修改原数组)arr.splice(1, 1, "a") → 替换索引1的元素截取与合并方法描述示例slice(start, end)截取子数组(不修改原数组)arr.slice(1, 3) → [2,3]concat(...arrays)合并多个数组,返回新数组arr.concat([4,5]) → [1,2,3,4,5]遍历与映射方法描述示例forEach(callback)遍历数组,执行回调函数arr.forEach((item) => console.log(item))map(callback)生成新数组(元素经回调处理)arr.map(x => x * 2) → [2,4,6]filter(callback)筛选符合条件的元素,生成新数组arr.filter(x => x > 1) → [2,3]reduce(callback)累计计算(如求和、求积)arr.reduce((sum, x) => sum + x, 0) → 6扩展运算符(Spread Operator)const arr1 = [1, 2]; const arr2 = [...arr1, 3]; // [1,2,3] const combined = [...arr1, ...arr2]; // [1,2,1,2,3]解构赋值const [first, second] = [1, 2]; console.log(first); // 1 console.log(second); // 2Array.from():将类数组对象如arguments转为数组const listItems = document.querySelectorAll("li"); const arr = Array.from(listItems); // 转为数组Array.find():查找第一个符合条件的元素。const user = users.find(u => u.id === 1);Array.some()/every():检测数组是否满足条件。arr.some(x => x > 3); // 是否存在大于3的元素 arr.every(x => x > 0); // 是否所有元素都大于012.3.实战示例去重const arr = [1, 2, 2, 3]; const uniqueArr = [...new Set(arr)]; // [1,2,3]扁平化嵌套数组const nested = [1, [2, [3]]]; const flat = nested.flat(Infinity); // [1,2,3]统计元素频率const arr = ["apple", "banana", "apple"]; const frequency = arr.reduce((acc, item) => { acc[item] = (acc[item] || 0) + 1; return acc; }, {}); // { apple: 2, banana: 1 }
2023年05月03日
125 阅读
0 评论
0 点赞
2023-05-01
【学习笔记】HTML和CSS基础
HTML1.1 浏览器浏览器内核名称核心技术架构开发者/维护方Google ChromeBlink(Chromium)基于 WebKit 分支,多进程架构Google(开源项目)Microsoft EdgeBlink(Chromium)同 Chrome,基于 Chromium 代码库MicrosoftMozilla FirefoxGecko独立渲染引擎,支持 Rust 和 WebAssemblyMozilla 基金会Apple SafariWebKit / Nitro基于 WebKit,JIT 编译优化AppleOperaBlink(Chromium)同 Chrome,基于 Chromium 代码库Opera Software ASA360/UC 浏览器Trident + Blink双核模式(兼容 IE + Chromium)奇虎 360/UCWeb性能对比指标BlinkGeckoWebKit页面加载速度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐JavaScript 性能⭐⭐⭐⭐⭐ (V8)⭐⭐⭐⭐ (SpiderMonkey)⭐⭐⭐ (Nitro)CSS 支持⭐⭐⭐⭐⭐(最新标准)⭐⭐⭐⭐⭐(严格模式)⭐⭐⭐⭐(部分滞后)内存占用⭐⭐(较高)⭐⭐⭐(中等)⭐⭐⭐⭐(较低)标准兼容性⭐⭐⭐⭐⭐⭐⭐⭐⭐(先锋)⭐⭐⭐(保守)1.2 HTML简介HTML全称HyperText Markup Language,超文本标记语言,超文本是一种组织信息的方式,它通过超级链接方法将文本中的文字、图表与其他信息媒体相关联。标签名不区分大小写,建议小写。参考资料:https://www.w3school.com.cn/<!DOCTYPE html><!-- html5声明 一般情况下可省略--> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <!-- 编码声明--> <title>标题</title> </head> <body> HTML内容 <input text=''> </body> </html>1.3基本属性1.3.1文档声明<!DOCTYPE html><!-- html5声明 一般情况下可省略-->1.3.2字符编码<meta charset="UTF-8"> <!-- 编码声明,写在head标签里-->1.3.3语言设置<html lang="zh-CN">zh-CN:中文-简体zh-TW:中文-繁体zh:中文en-US:英语-美国en-GB:英语-英国1.4常用标签1.4.1排版标签1.4.1.1 标题标签之间换行,不能互相嵌套一级标题二级标题三级标题四级标题五级标题六级标题<h1>一级标题</h1> <h2>二级标题</h2> <h3>三级标题</h3> <h4>四级标题</h4> <h5>五级标题</h5> <h6>六级标题</h6>1.4.1.2 div标签div间默认换行,可以嵌套其他标签<div> </div>1.4.1.3 段落不允许嵌套<p>段落</p>PS:块级元素:div、h1、P等:独占一行行级元素:span、input等不独占一行。行级元素内不允许写块元素1.4.2 文本标签em标签strong标签span标签>标签名语义单双em着重阅读的内容双strong十分重要,比em强烈双span没有寓意,包裹短语的通用容器双1.4.3 图片标签单标签<img src="">核心属性:属性名作用与枚举值示例src必填,指定图片资源路径: - 相对路径(images/logo.png) - 绝对 URL(https://example.com/image.jpg) - Base64 数据(data:image/png;base64,...)<img src="logo.png">alt必填,替代文本: - 描述性文字(alt="公司 Logo") - 装饰性图片设为空(alt="")<img src="deco-line.png" alt="">width/height显式设置图片尺寸(单位:像素): - 避免布局偏移(CLS) - 与 CSS 尺寸配合使用<img src="photo.jpg" width="800" height="600">loading加载行为: - lazy(延迟加载,视口外图片) - eager(立即加载,默认)<img src="banner.jpg" loading="lazy">srcset响应式图片源(分辨率/宽度适配): image-1x.jpg 1x, image-2x.jpg 2x image-480w.jpg 480w, image-800w.jpg 800w见下方响应式设计示例sizes媒体查询与显示宽度: (max-width: 600px) 480px, 800px见下方响应式设计示例<!-- 浏览器根据设备像素比(如 Retina 屏)自动选择高清图。 --> <img src="image-1x.jpg" srcset="image-1x.jpg 1x, image-2x.jpg 2x" alt="响应式图片">常见错误与解决方案问题场景解决方案图片不显示(404)检查 src 路径,确保服务器权限正确。布局偏移(CLS)显式设置 width 和 height,或使用 CSS aspect-ratio。移动端图片过大使用 srcset 按屏幕宽度加载合适尺寸,或通过 CDN 动态裁剪。透明背景锯齿使用 PNG 或 WebP 格式,避免 JPEG。1.4.4 超链接百度一下<a href="https://www.baidu.com">百度一下</a>常用属性:href:跳转链接指定网址:https://www.baidu.com相对路径的其他资源:./index.html连接到页面中其他元素:如#selector脚本:href="javascropt:alert('hello')"其他协议:比如 https://、ftp://、mailto:、file: 等,可以唤起其他应用target:跳转的目标_blank:新标签页_self:当前页面1.4.5列表有序列表(ordered): 列1 列2 <ol> <li>列1</li> <li>列2</li> </ol> 属性:type1(数字,默认)、A(大写字母)、a(小写字母)、I(大写罗马数字)、i(小写罗马数字)。推荐用 CSS 替代: list-style-type: decimal/upper-alpha/lower-roman;start整数(如 start="3",从 3 开始计数)。仅对数字类型有效。reversed布尔属性(倒序显示序号)。示例:<ol reversed>(兼容性较差,慎用)。无序列表(unordered) 选项1 选项2 <ul> <li>选项1</li> <li>选项2</li> </ul>自定义(definition) 1.选项 1.1.选项 2.选项 2.1.选项 <dl> <dt>1.选项</dt> <dd>1.1.选项</dd> <dt>2.选项</dt> <dd>2.1.选项</dd> </dl>注意事项:列表可以进行嵌套,例: 水果 苹果 香蕉 蔬菜 胡萝卜 西红柿 <ul> <li>水果 <ol> <li>苹果</li> <li>香蕉</li> </ol> </li> <li>蔬菜 <ul> <li>胡萝卜</li> <li>西红柿</li> </ul> </li> </ul>1.4.6表格 员工信息表 姓名 职位 部门 张三 前端工程师 技术部 李四 产品经理(兼UI设计) 总计:2 人 <table> <caption>员工信息表</caption> <colgroup> <col span="1" style="background-color: #f5f5f5"> <col span="2" style="width: 200px"> </colgroup> <thead> <tr> <th scope="col">姓名</th> <th scope="col">职位</th> <th scope="col">部门</th> </tr> </thead> <tbody> <tr> <td>张三</td> <td>前端工程师</td> <td>技术部</td> </tr> <tr> <td rowspan="2">李四</td> <td colspan="2">产品经理(兼UI设计)</td> </tr> </tbody> <tfoot> <tr> <td colspan="3">总计:2 人</td> </tr> </tfoot> </table> <table> 标签说明属性示例定义表格容器border:数值(如 1),控制表格边框宽度(已过时,推荐用 CSS)。width:数值或百分比(如 100%),定义表格宽度。<table border="1">...</table><table width="100%">注意事项避免使用 border 和 cellspacing,优先用 CSS 控制样式。 <tr> 标签说明属性示例定义表格行无特殊属性<tr><td>内容</td></tr>注意事项必须嵌套在 <table>、<thead>、<tbody> 或 <tfoot> 内。 <th> 标签说明属性示例定义表头单元格scope:col(关联列)、row(关联行)、colgroup(列组)、rowgroup(行组)。colspan:合并列数。rowspan:合并行数。<th scope="col">姓名</th><th colspan="2">合并表头</th><th rowspan="3">跨行表头</th>注意事项必须用 scope 属性提升可访问性(屏幕阅读器友好)。 <td> 标签说明属性示例定义表格数据单元格colspanrowspan<td colspan="2">合并单元格</td><td rowspan="3">跨行单元格</td>注意事项避免滥用合并,保持表格结构清晰。 <thead>, <tbody>, <tfoot> 标签标签名说明示例注意事项<thead>定义表头区域<thead><tr><th>标题</th></tr></thead>必须位于 <table> 内,且顺序为 <thead> → <tbody> → <tfoot>。<tbody>定义表格主体内容<tbody><tr><td>数据</td></tr></tbody>可包含多个 <tbody> 分段管理数据。<tfoot>定义表格底部汇总信息<tfoot><tr><td>总计</td></tr></tfoot>必须位于 <tbody> 之后。 <caption> 标签说明属性示例注意事项定义表格标题无特殊属性<caption>2023 年销售数据</caption>必须紧跟在 <table> 开始标签后。<colgroup> 和 <col> 标签标签名说明属性示例<colgroup>定义表格列组span(合并列数)<colgroup span="2" style="background:#eee"></colgroup><col>定义单列样式span(合并列数)<colgroup><col span="2" style="width:100px"></colgroup>注意事项用于批量控制列宽或样式,需配合 CSS 使用。 1.4.7.form表单<form action="/submit" method="POST" enctype="multipart/form-data"> <!-- 输入控件 --> <input type="text" name="username" required> <button type="submit">提交</button> </form>属性名枚举值/用法示例说明注意事项methodGET(数据附加到 URL) POST(数据在请求体中)表单提交的 HTTP 方法。GET 适合非敏感数据POST 适合文件上传或敏感信息。enctypeapplication/x-www-form-urlencoded(默认编码) multipart/form-data(文件上传) text/plain(纯文本)表单数据的编码方式。文件上传必须设为 multipart/form-data。action/submit(提交到服务器接口) javascript:void(0)(JS 处理) 空值(当前页面)表单提交的目标地址。使用 javascript: 需绑定 onsubmit 事件处理。1.4.8.input标签type属性:type 值用途与特性示例text单行文本输入(默认)<input type="text" name="username">password密码输入(隐藏内容)<input type="password" name="pwd">email邮箱输入(触发格式验证)<input type="email" name="email">number数字输入(支持 min/max/step)<input type="number" min="1" max="100" step="1">file文件上传(需 enctype="multipart/form-data")<input type="file" name="avatar" accept="image/*">checkbox多选框<input type="checkbox" name="hobby" value="reading">radio单选框(相同 name 分组)<input type="radio" name="gender" value="male">submit提交按钮<input type="submit" value="提交">hidden隐藏字段(存储无需用户输入的数据)<input type="hidden" name="token" value="abc123">其他关键属性属性名作用示例required必填字段(触发浏览器验证)<input type="text" required>placeholder输入提示文本<input placeholder="请输入用户名">pattern正则表达式验证(需配合 title 提示)<input pattern="[A-Za-z]{3}" title="3位字母">readonly只读字段(值可提交)<input type="text" value="固定值" readonly>disabled禁用字段(值不提交)<input type="text" disabled>其他表单控件:<textarea> 多行文本输入<textarea name="comment" rows="4" cols="50" placeholder="请输入评论"></textarea><select> 下拉选择<select name="city"> <option value="">请选择城市</option> <option value="shanghai">上海</option> <option value="beijing">北京</option> </select><fieldset> 和 <legend> 分组控件<fieldset> <legend>用户信息</legend> <input type="text" name="username"> <input type="email" name="email"> </fieldset>1.4.9 iframe<iframe>(内联框架)用于在当前 HTML 页面中嵌入另一个独立的 HTML 文档。常见用途包括:嵌入第三方内容(如地图、视频、广告)。展示沙盒化内容(如代码编辑器预览)。实现页面局部刷新(传统用法,现代开发中已较少使用)。核心属性属性名说明常用值/示例src指定嵌入内容的 URL(必填)。src="https://example.com" src="local-page.html"width & height定义框架的宽高(单位:像素或百分比)。width="800" height="600" width="100%"frameborder是否显示边框(已过时,推荐用 CSS 替代)。0(无边框)或 1(有边框)。allow控制嵌入内容的功能权限(安全关键属性)。allow="fullscreen"(允许全屏) allow="camera; microphone"(设备权限)sandbox启用沙盒模式,限制嵌入页面的行为(安全关键属性)。sandbox="allow-scripts"(仅允许脚本) sandbox="allow-forms"(允许表单提交)loading控制框架加载时机(优化性能)。loading="lazy"(延迟加载) loading="eager"(立即加载)name为框架命名,用于超链接的 target 属性。<a href="page.html" target="my-frame">打开链接</a> 安全注意事项防止点击劫持(Clickjacking)方法一:通过响应头禁止被嵌入。Content-Security-Policy: frame-ancestors 'none'方法二:在嵌入的页面中添加以下代码:<script> if (window !== window.top) { window.top.location = window.location; } </script>2. 沙盒模式(Sandbox)严格模式:禁止所有功能。<iframe src="external.html" sandbox></iframe>允许部分功能:按需开放权限。<iframe sandbox="allow-scripts allow-same-origin"></iframe>3. 跨域限制(CORS)嵌入跨域内容时,需确保目标页面设置了允许嵌入的 CORS 头:Access-Control-Allow-Origin: *示例代码嵌入 YouTube 视频<iframe width="560" height="315" src="https://www.youtube.com/embed/视频ID" title="YouTube 视频" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe>嵌入 Google 地图<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d坐标参数" width="600" height="450" style="border:0;" allowfullscreen loading="lazy" ></iframe>沙盒化代码预览<iframe sandbox="allow-scripts" srcdoc="<script>alert('安全沙盒中的代码');</script>" ></iframe>5. 替代方案现代替代:优先使用 Web Components 或前端框架(如 React、Vue)的组件化方案。动态加载:通过 JavaScript 的 fetch() 或 XMLHttpRequest 加载内容并插入到 DOM 中。1.4.10 meta标签html基本信息<head> <meta charset="UTF-8"> <meta name="description" content="免费的 Web 教程"> <meta name="keywords" content="HTML, CSS, JavaScript"> <meta name="author" content="Bill Gates"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head>width=device-width 部分将页面的宽度设置为跟随设备的屏幕宽度(视设备而定)。当浏览器首次加载页面时,initial-scale=1.0 部分设置初始缩放级别。meta标签还可以使用html的全局属性1.5.HTML5新增标签1.5.1语义化标签标签说明属性示例注意事项<header>定义页面或区块的页眉(如导航栏、Logo)。无特殊属性一个页面可包含多个 <header>,通常位于顶部。<footer>定义页面或区块的页脚(如版权信息、联系方式)。无特殊属性可嵌套在 <article> 或 <section> 内。<nav>定义导航链接集合(如主导航菜单)。无特殊属性仅用于主要导航,次要链接无需包裹。<article>定义独立内容块(如博客文章、新闻条目)。无特殊属性内容应自包含,适合单独分发或复用。<section>定义文档中的章节或区块(如章节、标签页)。无特殊属性需搭配标题(<h2>~<h6>)使用。<aside>定义与主内容相关的侧边栏或附加内容(如引用、广告)。无特殊属性内容应与主内容相关,但非必需。<main>定义文档主体内容(每个页面唯一)。无特殊属性不可嵌套在 <header>、<footer> 或 <article> 内。<figure>定义媒体内容组合(如图片、图表、代码块)。无特殊属性需配合 <figcaption> 添加标题或说明。<time>定义时间或日期。datetime(机器可读格式,如 datetime="2023-10-01")示例:<time datetime="2023-10-01">国庆节</time>。1.5.2.多媒体标签标签说明属性示例注意事项<video>嵌入视频文件。controls(显示控件)、autoplay(自动播放)、poster(封面图)。提供多种格式(如 MP4、WebM)以提高兼容性。<audio>嵌入音频文件。controls、loop(循环播放)、muted(静音)。支持 MP3、WAV、Ogg 等格式。<track>为 <video> 或 <audio> 添加字幕或章节信息。kind(类型,如 subtitles)、src(字幕文件路径)、srclang(语言)。示例:<track src="subs_en.vtt" kind="subtitles" srclang="en">。1.5.3.图形与交互标签标签说明属性示例注意事项<canvas>通过 JavaScript 绘制图形、动画或游戏。width、height(画布尺寸)。需配合 JS 使用,示例:<canvas id="myCanvas" width="800" height="600"></canvas>。<svg>定义矢量图形(如图标、图表)。viewBox(视口)、fill(填充颜色)、stroke(描边颜色)。直接嵌入 SVG 代码或通过 <img> 引用外部文件。1.5.4.表单增强标签标签/属性说明属性示例注意事项<datalist>定义输入框的预定义选项列表(与 <input list> 配合使用)。id(与 <input list> 属性关联)。示例:<input list="browsers"><datalist id="browsers"><option value="Chrome"></datalist>。<output>显示计算或用户输入的结果。for(关联的输入控件 ID)。需通过 JS 更新值。<input type="email">邮箱输入(自动格式验证)。multiple(允许多个邮箱,用逗号分隔)。需后端二次验证。<input type="date">日期选择器。min、max(限制日期范围)。浏览器样式可能不一致。<input type="range">滑块控件。min、max、step(步长)。示例:<input type="range" min="0" max="100" step="10">。1.5.5.其他新增标签标签说明属性示例注意事项<mark>高亮显示文本(如搜索结果关键词)。无特殊属性示例:<p>这是<mark>高亮</mark>文本。</p>。<progress>显示任务进度条。value(当前值)、max(最大值)。示例:<progress value="70" max="100"></progress>。<meter>显示标量测量值(如磁盘使用量)。min、max、value、low、high(阈值范围)。示例:<meter value="6" min="0" max="10">6/10</meter>。<dialog>定义对话框或模态窗口。open(默认显示)。 1.5.6.兼容性与最佳实践兼容性处理:旧版 IE(IE8及以下)不支持 HTML5 标签,需通过以下代码启用:<!--[if lt IE 9]> <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script> <![endif]-->语义化优先替代 <div class="header"> 为 <header>,提升 SEO 和可访问性。使用 <picture> 和 srcset 适配不同设备分辨率。表单验证结合 HTML5 原生验证(如 required、pattern)与 JS 自定义逻辑。1.6.单双标签列表1.6.1.单标签单标签不需要结束标签,通常用于插入元素或执行动作,不可包含内容。常见单标签:标签作用示例<br>强制换行第一行<br>第二行<hr>水平分割线<hr style="border: 1px solid #ccc;"><img>插入图片<img src="image.jpg" alt="描述"><input>输入控件(文本、密码、文件等)<input type="text" name="username"><meta>定义元数据(字符编码、视口等)<meta charset="UTF-8"><link>引入外部资源(CSS、图标等)<link rel="stylesheet" href="style.css"><area>定义图像映射区域(需配合 <map> 使用)<area shape="rect" coords="0,0,82,126" href="link.html"><base>设置页面的基础 URL<base href="https://example.com/">特殊说明:单标签在 HTML5 中可以省略斜杠(如 <br>),但在 XHTML 中需强制闭合(如 <br />)。<img>、<input> 等标签即使没有内容,也需保持自闭合格式。1.6.2.双标签双标签必须成对出现,用于定义结构或包含内容。常见双标签:标签作用示例<div>通用块级容器<div class="container"><p>内容</p></div><p>段落<p>这是一段文字。</p><h1>~<h6>标题(1 级最大,6 级最小)<h1>主标题</h1><a>超链接<a href="https://example.com">链接</a><ul>/<ol>无序列表/有序列表<ul><li>项目1</li></ul><table>表格<table><tr><td>单元格</td></tr></table><form>表单容器<form action="/submit" method="POST"></form><script>嵌入或引用 JavaScript 代码<script src="app.js"></script>特殊说明:双标签必须严格闭合,否则会导致页面渲染错误(如未闭合的 <div> 会影响后续布局)。部分双标签可嵌套单标签,例如 <p> 中包含 <br> 或 <img>。1.6.3常见混淆点场景正确用法错误用法自闭合标签<img src="image.jpg">(正确)<img src="image.jpg"></img>(错误,双标签闭合)双标签闭合<div><p>内容</p></div><div><p>内容</p>(错误,未闭合 <div>)特殊双标签<br>(单标签)不能写成 <br></br><br></br>(错误,单标签无需闭合)如何验证标签闭合?浏览器开发者工具:按 F12 打开控制台,若标签未闭合会提示 Error: Unclosed element。在线验证工具:使用 W3C Validator 检查 HTML 语法。CSS1.样式编写方式行内:<div style="width: 100px"/>内部:<style></style>外部:<link rel="stylesheet" href="./XX.css">优先级:行内 > 内部 = 外部2.语法规范h1{ colr: green; font-size: 40px; }选择器:{属性名:属性值;属性名:属性值}3.选择器3.1 通配选择器* { 属性名:属性值 }3.2 元素选择器通过元素标签进行选择h1{ colr: green; font-size: 40px; }3.3 类选择器元素标签定义class属性.class<div class="student"></div> .student{ }3.4 ID选择器元素标签定义ID#ID<div id="student"></div> #student{ }3.5 复合选择器交集选择器:既是,又是p.class#id{ }并集选择器:A和B都选择p, .class, #id{ }3.6 后代选择器选择某元素的后代元素,中间用空格隔开div span{ } .student #zangsan{ }3.7 子代选择器选择器>选择器,选择某元素的子元素(非孙)div > a{ }3.8 兄弟选择器选择器+选择器,选择某元素的相邻的兄弟元素。如果不相邻,则找不到。div+a{ }选择器~选择器,选择某元素后所有的兄弟元素div~a{}3.9 属性选择器[title]或者[title="t1"]选中具有某个属性,或者某属性值为?的元素[title]{ } [title="t1"]{ } [title^="t"]{}/*以t开头的*/ [title$="t"]{}/*以t结尾的*/ [title*="t"]{}/*存在字母t的*/3.10 伪类选择器根据元素的状态、位置或特定条件来定义样式,而无需在 HTML 中显式添加类名或 ID。语法格式:以冒号 : 开头,例如 :hover、:nth-child()。a:link{} a:visited{}3.10.1. 元素状态相关伪类选择器描述示例:hover鼠标悬停在元素上时生效a:hover { color: red; }:focus元素获得焦点时生效(如输入框、按钮)input:focus { border: 2px solid blue; }:active元素被点击(激活)时生效button:active { transform: scale(0.95); }:visited链接已被访问过时生效(需谨慎使用,受浏览器安全限制)a:visited { color: purple; }3.10.2. 元素位置相关伪类选择器描述示例:nth-child(n)选择父元素中的第 n 个子元素li:nth-child(odd) { background: #f0f0f0; }an+b(n自增);odd(奇数)、even(偶数):first-child选择父元素的第一个子元素p:first-child { font-weight: bold; }:last-child选择父元素的最后一个子元素tr:last-child { border-bottom: 2px solid #ccc; }:not(selector)排除符合指定选择器的元素div:not(.special) { margin: 0; }:first-of-type满足条件的第一个子元素div>p:first-of-type{}:last-of-type满足条件的最后一个 :nth-of-type满足条件的n个子元素 3.10.3. 表单相关伪类选择器描述示例:checked单选框/复选框被选中时生效input[type="checkbox"]:checked + label { color: green; }:disabled表单元素被禁用时生效button:disabled { opacity: 0.5; }:required表单字段带有 required 属性时生效input:required { border: 1px solid red; }3.10.4. 特殊场景伪类选择器描述示例:targetURL 锚点指向的元素(如 #section1)#section1:target { display: block; }:root匹配文档根元素(通常是 <html>):root { --primary-color: #333; }3.10.5.伪类 vs 伪元素特性伪类(Pseudo-class)伪元素(Pseudo-element)用途匹配元素的状态或位置操作元素的特定部分(如首行、首字母)语法单冒号 :(如 :hover)双冒号 ::(如 ::before)是否创建新内容否(仅改变现有元素的样式)是(可插入生成内容,如 ::before)示例li:hover, input:focusp::first-line, ::selection3.11伪元素选择器操作元素的特定部分,如首行、首字母。可插入生成内容伪类选择器描述::first-letter第一个文字::firstline第一行文字::selection被鼠标选中的文字::before在某某元素之前插入::after在某某元素之后插入3.12.选择器优先级通常情况:行内样式>ID选择器>类选择器>元素选择器>通配选择器。复杂情况:按照ID选择器个数,类、伪类、属性选择器的个数,元素、伪元素选择器的个数依次比较优先级。相同情况覆盖。如特殊情况:属性值后!important。最优先.container span.slogan{} /*0,2,1*/ div>p>span:nth-child(1) /*0,1,3*/4.CSS特性层叠性:相同元素的相同样式会覆盖继承性:元素自动拥有父元素或祖父元素所设置的某些样式,优先继承离得近的。比如text-??、font-、line、color优先级:样式拥有优先级。5.颜色5.1. 颜色名称(Named Colors)CSS 预定义了 140 多个标准颜色名称(如 red, blue, black 等)。优点:简单易记,适合快速开发。缺点:颜色范围有限,无法精确控制。.color-example { color: red; background: lightblue; }5.2. 十六进制(Hex Codes)格式:#RRGGBB 或简写 #RGB(每位重复一次)。支持透明度:#RRGGBBAA 或 #RGBA。.hex-example { color: #ff0000; /* 纯红色 */ background: #fff; /* 白色简写 */ border-color: #4a5b6c; /* 自定义颜色 */ opacity: 0.8; /* 整体透明度(影响子元素) */ }5.3. RGB 函数(RGB)格式:rgb(red, green, blue),取值范围 0-255。支持透明度:rgba(red, green, blue, alpha),alpha 范围 0-1。css复制.rgb-example { color: rgb(255, 0, 0); /* 纯红色 */ background: rgba(0, 0, 255, 0.5); /* 半透明蓝色 */ }5.4. HSL 函数(Hue, Saturation, Lightness)Hue(色相): 0-360°(角度,如 0° 红色,120° 绿色)。Saturation(饱和度): 0-100%(百分比,控制色彩鲜艳度)。Lightness(亮度): 0-100%(百分比,控制明暗)。支持透明度:hsla(hue, saturation, lightness, alpha)。.hsl-example { color: hsl(0, 100%, 50%); /* 纯红色 */ background: hsla(120, 100%, 50%, 0.3); /* 半透明绿色 */ }5.5. 预处理器变量(CSS Variables)自定义颜色变量,提高代码复用性。:root { --primary-color: #2196F3; --secondary-color: rgba(255, 152, 0, 0.8); } .custom-colors { color: var(--primary-color); border: 2px solid var(--secondary-color); }5.6. HSLA 透明度通过 hsla() 实现颜色透明度的精细控制。.overlay { background: hsla(0, 0%, 0%, 0.5); /* 半透明黑色 */ }5.7. 字符串形式直接使用颜色关键字或十六进制值作为字符串。.string-example { color: "red"; /* 等效于 red */ background: "#00ff00"; /* 等效于 #0f0 */ }5.8. 透明黑色(RGBA 黑色)常用于遮罩层或文字阴影。.modal-backdrop { background: rgba(0, 0, 0, 0.7); }5.9. 线性渐变(Linear Gradient)使用 linear-gradient() 创建颜色过渡。.gradient-example { background: linear-gradient(to right, #ff7e5f, #feb47b); }5.10. Lab/CIEDE2000(高级颜色模型)现代浏览器支持的实验性功能,用于更精确的颜色匹配。.lab-color { color: color(lab(50% 60% 30%)); }注意事项颜色对比度:确保文本与背景对比度符合 WCAG 标准(至少 4.5:1)。浏览器兼容性:hsl() 和 rgba() 在 IE9+ 支持。color() 函数(如 Lab)仅在部分现代浏览器中支持。性能优化:避免过度使用复杂颜色函数(如 hsl() 嵌套计算)。总结方式适用场景示例十六进制快速开发、简单颜色#ff0000RGB/RGBA需要透明度或编程逻辑控制rgba(255, 0, 0, 0.5)HSL/HSLA动态调整明暗、饱和度(如主题切换)hsl(0, 100%, 50%)CSS 变量主题化、跨组件复用--primary-color: #2196F3渐变背景、装饰效果linear-gradient(...)根据具体需求选择最合适的颜色表示方式,例如:设计稿还原:直接使用十六进制或 RGB。动态主题:优先使用 HSL 或 CSS 变量。透明度需求:使用 RGBA 或 HSLA。6.常用CSS属性6.1.布局与盒模型属性描述示例display定义元素的显示类型(块级、行内、弹性、网格等)display: flex;position定位方式(静态、相对、绝对、固定、粘性)position: relative;top/right/bottom/left定位元素偏移量top: 20px;margin外边距(控制元素间距)margin: 10px 5px;padding内边距(控制内容与边框距离)padding: 15px;width/height元素宽高width: 100%;box-sizing盒模型计算方式(content-box 或 border-box)box-sizing: border-box;6.2.字体与文本属性描述示例color文本颜色color: #333;font-size字体大小font-size: 16px;font-family字体类型font-family: Arial, sans-serif;text-align文本水平对齐(左、右、居中、两端对齐)text-align: center;line-height行高line-height: 1.5;text-decoration文本装饰线(如下划线)text-decoration: none;letter-spacing字符间距letter-spacing: 1px;6.3.背景与边框属性描述示例background-color背景颜色background-color: #f0f0f0;background-image背景图片background-image: url("img.jpg");background-size背景图片尺寸(cover、contain)background-size: cover;border边框(宽度、样式、颜色)border: 1px solid #ccc;border-radius圆角半径border-radius: 8px;box-shadow阴影效果(水平偏移、垂直偏移、模糊、颜色)box-shadow: 2px 2px 10px rgba(0,0,0,0.1);6.4.Flexbox 布局属性描述示例display: flex启用弹性容器display: flex;flex-direction主轴方向(行、列等)flex-direction: row-reverse;justify-content主轴对齐方式(居中、两端对齐等)justify-content: space-between;align-items交叉轴对齐方式align-items: center;flex-grow子元素弹性伸展比例flex-grow: 1;flex-shrink子元素弹性收缩比例flex-shrink: 0;6.5.Grid 布局属性描述示例display: grid启用网格容器display: grid;grid-template-columns定义列宽(如 1fr 2fr)grid-template-columns: repeat(3, 1fr);gap网格间距gap: 10px;grid-row/grid-column定义子元素位置grid-column: 1 / 3;6.6.响应式与视口属性描述示例max-width最大宽度(防止元素过宽)max-width: 1200px;min-height最小高度min-height: 300px;@media媒体查询(响应式设计)@media (max-width: 768px) { ... }6.7.动态效果属性描述示例transition过渡效果(属性、时长、缓动函数)transition: all 0.3s ease;animation关键帧动画(名称、时长、延迟等)animation: slide 2s infinite;6.8.其他常用属性属性描述示例opacity透明度(0~1)opacity: 0.8;visibility元素可见性(visible/hidden)visibility: hidden;z-index层叠顺序(解决重叠元素的显示问题)z-index: 10;cursor鼠标悬停样式cursor: pointer;6.9.CSS 自定义属性(变量):root { --primary-color: #2196F3; } .element { background: var(--primary-color); }6.10伪类与伪元素属性描述示例content伪元素内容(需配合 ::before/::after)content: "→";::placeholder输入框占位符样式::placeholder { color: gray; }7.元素显示模式7.1. 块级元素(Block-level Elements)特点:独占一行:默认情况下,块级元素会从上到下独占一行,无论内容宽度是否填满父容器。可设宽高:可以通过 width 和 height 直接设置尺寸。宽度默认值:若未设置宽度,默认撑满父容器的剩余空间(width: 100%)。支持内外边距:margin 和 padding 在四个方向均有效。常见标签:<div>,<p>, <h1>~<h6>, <ul>, <li>, <form>, <header>, <footer>, <section>示例:<div style="background: lightblue;"> 这是一个块级元素,默认占满整行,可以设置宽高。 </div> <span style="background: lightgreen;">这是一个行内元素,不会独占一行。</span>6.2. 行内元素(Inline Elements)特点:不独占一行:多个行内元素会在同一行内依次排列,直到容器宽度不足才会换行。不可设宽高:width 和 height 对行内元素无效,尺寸由内容决定。宽度默认值:仅等于内容的宽度。内外边距限制:margin 和 padding 仅在水平方向(左右)生效,垂直方向(上下)会被忽略。常见标签:<a>, <span>, <strong>, <em>, <img>, <br>, <input>, <button>示例:<span style="background: pink;">行内元素 A</span> <span style="background: yellow;">行内元素 B</span> <!-- 两者会在同一行显示 -->6.3. 行内块元素(Inline-block Elements)特点:不独占一行:与行内元素类似,多个行内块元素会在同一行排列。可设宽高:与块级元素类似,可以直接设置 width 和 height。内外边距完整:margin 和 padding 在四个方向均有效,与块级元素一致。常见标签:<img>, <input>, <button>, <textarea>(也可以通过 display: inline-block 将普通元素转为行内块)示例:<div style="background: orange;" class="inline-block">行内块元素 1</div> <div style="background: cyan;" class="inline-block">行内块元素 2</div>.inline-block { display: inline-block; width: 100px; height: 50px; }6.4.核心区别对比表特性块级元素行内元素行内块元素换行独占一行不独占不独占宽高控制支持 width/height不支持支持内外边距四向均有效水平有效,垂直无效四向均有效默认宽度父容器剩余空间内容宽度由内容或 width 决定典型用途页面布局、结构划分文本内嵌元素灵活排列且需尺寸控制的元素6.5.如何切换显示类型通过 display 属性可以强制转换元素的显示类型:.element { display: block; /* 转为块级元素 */ display: inline; /* 转为行内元素 */ display: inline-block; /* 转为行内块元素 */ }示例:<span style="display: block; background: gray;">被转为块级的 span</span> <div style="display: inline; background: brown;">被转为行内的 div</div>6.6.注意事项块级元素嵌套规则:块级元素可以包含行内元素或其他块级元素,但行内元素不能直接包含块级元素。图片默认行为:<img> 是行内块元素,因此可以直接设置宽高,无需额外转换。清除默认样式:部分块级元素(如 ul、p)有默认外边距或内边距,需用 margin: 0; padding: 0; 重置。8.盒子模型8.1.盒子模型的组成每个元素被视为一个矩形盒子,包含四个部分:内容区域(Content)元素的实际内容(文本、图片等)。由 width 和 height 定义尺寸。内边距(Padding)内容与边框之间的空白区域。由 padding-top、padding-right、padding-bottom、padding-left 控制。边框(Border)包围内边距和内容的线框。由 border-width、border-style、border-color 定义。外边距(Margin)元素与其他元素之间的空白区域。由 margin-top、margin-right、margin-bottom、margin-left 控制。8.2.总宽高的计算盒子的总宽高由以下公式计算:总宽度 = width + padding-left + padding-right + border-left-width + border-right-width 总高度 = height + padding-top + padding-bottom + border-top-width + border-bottom-width关键属性:box-sizingcontent-box(默认值)width 和 height 仅包含内容区域,不包含 padding 和 border。示例:.box { width: 200px; padding: 20px; border: 5px solid black; box-sizing: content-box; /* 总宽度 = 200 + 20 * 2 + 5 * 2 = 250px */ }border-boxwidth 和 height 包含内容、padding 和 border,内容区域会缩小。示例:.box { width: 200px; padding: 20px; border: 5px solid black; box-sizing: border-box; /* 总宽度固定为 200px,内容宽度 = 200 - (20 * 2 + 5 * 2) = 150px */ }推荐实践:全局设置 box-sizing: border-box 以简化布局计算:*, *::before, *::after { box-sizing: border-box; }8.3.外边距折叠(Margin Collapsing)在垂直方向上,相邻的两个块级元素的外边距会合并为一个较大的外边距,取两者中的较大值。触发条件相邻的兄弟元素。父元素与第一个/最后一个子元素(无 padding 或 border 隔开)。空块级元素(无内容、padding、border)。解决方法为父元素添加 padding 或 border。使用 overflow: hidden 或 float 触发 BFC(块级格式化上下文)。设置 margin 为 0。8.4.内边距与边框的影响内容区域缩小:若未使用 border-box,padding 和 border 会增加元素总尺寸,导致内容区域被压缩。背景渲染:background-color 会覆盖 content、padding 和 border 区域。8.5.实际应用示例按钮样式.button { display: inline-block; padding: 12px 24px; border: 2px solid #333; background: #f0f0f0; margin: 10px; /* 外边距控制按钮间距 */ box-sizing: border-box; /* 确保宽高包含所有部分 */ }响应式布局.container { width: 100%; max-width: 1200px; margin: 0 auto; /* 居中 */ padding: 20px; box-sizing: border-box; /* 总宽度始终 ≤ 1200px */ }8.6.总结特性内容(content)内边距(padding)边框(border)外边距(margin)作用显示元素的核心内容控制内容与边框距离定义元素边界控制元素间间距是否影响总尺寸否(除非 box-sizing)是是是默认值由内容决定0none0常用场景文本、图片按钮内边距卡片边框页面边距元素空白问题:行内元素和行内块元素之间会存在空白间隙<div> <span>1</span><!-- 取消换行也行 --> <span>1</span> <span>1</span> </div> <style> div { font-size: 0px /*设置字体为0*/ } span { font-size: 10px } </style>行内块的幽灵空白问题行内块元素与文本的基线对齐,而文本的基线与文本最底端之间是有一定距离的。方案一:给行内块设置vertical,值不为baseline即可,设置为middel、bottom、top均可方案二:若父元素中只有一张图片,设置图片为display:block。方案三:给父元素设置font-size:0。再单独设置其他文本。9.浮动9.1.浮动的核心概念1. 基本定义float 属性:用于将元素向左(left)或向右(right)移动,使其脱离正常文档流,其他内容围绕其排列。初始值:none(元素不浮动)。2. 语法.element { float: left | right | none; }9.2.浮动的行为特性1. 脱离文档流浮动元素不再占据原文档流的位置,其他块级元素会忽略其存在,但行内元素会围绕它排列。示例:文本环绕图片(经典用法)。<img src="image.jpg" style="float: left; margin: 10px;"> <p>文本内容会环绕在图片右侧...</p>2. 宽高影响浮动元素的宽高由其内容或显式设置的 width/height 决定。默认宽度:若未设置宽度,浮动元素宽度为内容宽度。3. 父容器高度塌陷问题:当父容器仅包含浮动元素时,其高度会塌陷为 0。原因:浮动元素脱离文档流,父容器无法感知其高度。解决方案:方法 1:添加清除浮动元素<div class="parent"> <div class="float-left"></div> <div class="float-left"></div> <div style="clear: both;"></div> <!-- 清除浮动 --> </div>方法 2:使用伪元素清除浮动(推荐).parent::after { content: ""; display: table; clear: both; }方法 3:触发 BFC(块级格式化上下文).parent { overflow: hidden; /* 或 float、position 等 */ }9.3.浮动的应用场景1. 多栏布局经典两列布局:左侧固定宽度,右侧自适应。<div class="container"> <div class="left-column" style="float: left; width: 200px;">左侧内容</div> <div class="right-column">右侧内容自适应</div> </div>.right-column { margin-left: 200px; /* 为左侧留出空间 */ }2. 图文混排图片环绕文字:通过img { float: left; margin: 0 10px 10px 0; }3. 旧版布局替代方案在 Flexbox/Grid 出现前,浮动是实现复杂布局的主要手段(现已被取代)。9.4.浮动的常见问题与解决1. 元素间隙问题现象:浮动元素间因换行符产生空白间隙。原因:空白字符(空格、换行)被渲染为小间隙。解决方案:移除 HTML 中的多余空格或换行。设置父元素,再重置子元素字体大小。font-size: 0.parent { font-size: 0; } .child { font-size: 16px; /* 恢复子元素字体 */ }2. 父容器高度塌陷参见上文解决方案(清除浮动或触发 BFC)。3. 元素覆盖问题现象:浮动元素可能覆盖其他非浮动元素。解决:调整 z-index 或避免过度嵌套。10.定位10.1. 静态定位(static)默认值:所有元素均为静态定位。特点:元素按正常文档流排列。top/right/bottom/left 无效。示例:.element { position: static; /* 可省略 */ }10.2. 相对定位(relative)特点元素相对于其正常位置偏移(通过 top/right/bottom/left)。不脱离文档流,其他元素仍按原位置排列。可作为定位上下文(子元素的 absolute 会相对于它)。示例.box { position: relative; top: 20px; /* 向下偏移 20px */ left: 30px; /* 向右偏移 30px */ }10.3. 绝对定位(absolute)特点:元素脱离文档流,相对于最近的已定位祖先(position 值非 static 的祖先)定位。若无已定位祖先,则相对于初始包含块(通常是 <html> 或视口)。需配合 top/right/bottom/left 使用。应用场景:弹窗、下拉菜单、遮罩层。示例:.parent { position: relative; /* 成为定位上下文 */ } .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); /* 居中 */ }10.4. 固定定位(fixed)特点:元素脱离文档流,相对于视口(viewport) 定位。滚动页面时位置不变。常用于导航栏、侧边栏、返回顶部按钮。注意事项:移动端视口需设置 <meta name="viewport">。示例:.fixed-nav { position: fixed; top: 0; left: 0; width: 100%; z-index: 1000; /* 确保在最上层 */ }10.5. 粘性定位(sticky)特点:元素在滚动时在特定阈值前保持相对定位,超过后变为固定定位。需设置 top/right/bottom/left 阈值。应用场景:吸顶导航栏、表格表头固定。示例:.sticky-header { position: sticky; top: 0; background: white; }10.6.定位上下文(Containing Block)定义:元素定位的参考容器。如何确定:根元素(<html>)的包含块是视口。普通元素的包含块由其最近的块级祖先的 content 区域决定。绝对定位元素的包含块由最近的已定位祖先(position: relative/absolute/fixed/sticky)决定。10.7.偏移属性(top/right/bottom/left)作用:指定元素相对于其定位上下文的偏移量。取值:length(如 20px)、percentage(相对于包含块宽度/高度)。注意:若同时设置 top 和 bottom,仅生效其中一个(取决于布局)。百分比值在绝对定位中基于包含块尺寸,相对定位中基于自身尺寸。10.8.层叠顺序(z-index)作用:控制定位元素的堆叠顺序(谁在上层)。规则:正值比负值上层。数值越大,层级越高。父元素的 z-index 会影响子元素层级。注意:仅对定位元素(relative/absolute/fixed/sticky)有效。避免过度依赖 z-index,可能导致维护困难。10.9.常见布局场景1. 固定侧边栏.sidebar { position: fixed; right: 0; top: 0; width: 250px; height: 100vh; }2. 居中弹窗.modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); }3. 粘性吸顶.header { position: sticky; top: 0; background: #fff; z-index: 100; }10.10注意事项避免过度使用 absolute/fixed:过度脱离文档流可能导致布局混乱,优先考虑 Flexbox/Grid。父容器高度塌陷:绝对定位元素会导致父容器高度塌陷,需用 padding/margin 或伪元素清除。移动端兼容性:position: fixed 在 iOS 的软键盘弹出时可能异常,需特殊处理。响应式设计:固定定位元素在移动端可能遮挡内容,需结合媒体查询调整。10.11总结定位类型脱离文档流定位参考典型用途static否正常文档流默认布局relative否自身正常位置微调元素位置absolute是最近的已定位祖先弹窗、下拉菜单fixed是视口固定导航栏、返回顶部按钮sticky条件性脱离视口或父容器阈值吸顶导航栏、表格表头11.常用布局名词11.1语义化类名位置名词顶部导航条topbar页头header、page-header导航nav、navigator、navbar搜索框search、search-box横幅、广告、宣传图banner主要内容content、main侧边栏aside、sidebar页脚footer、page-footer类名用途示例(HTML).header页面头部<header class="header">...</header>.footer页面底部<footer class="footer">...</footer>.main-content主要内容区域<main class="main-content">...</main>.sidebar侧边栏<aside class="sidebar">...</aside>.card卡片式布局容器<div class="card">...</div>11.2.基础布局类类名用途示例(CSS).container页面或区域的容器,通常用于限制宽度并居中max-width: 1200px; margin: 0 auto;.wrapper包裹内容的通用容器padding: 20px;.rowFlexbox/Grid 中的行容器,用于水平排列子元素display: flex; flex-wrap: wrap;.col列容器,用于垂直排列内容flex: 1;.cell网格单元格(Grid 布局)grid-area: 1 / 1 / 2 / 3;11.3.Flexbox 布局类类名用途示例(CSS).flex启用 Flexbox 布局display: flex;.flex-row水平方向排列(默认)flex-direction: row;.flex-col垂直方向排列flex-direction: column;.flex-center子元素水平和垂直居中justify-content: center; align-items: center;.flex-gap-*设置子元素间距(如 .flex-gap-20 表示 20px)gap: 20px;.flex-fill子元素填充剩余空间flex: 1;.flex-basis-*设置子元素初始宽度(如 .flex-basis-200 表示 200px)flex-basis: 200px;11.4.Grid 布局类类名用途示例(CSS).grid启用 Grid 布局display: grid;.grid-cols-*定义列数(如 .grid-cols-3 表示 3 列)grid-template-columns: repeat(3, 1fr);.grid-rows-*定义行高(如 .grid-rows-100 表示每行 100px)grid-template-rows: 100px;.grid-gap-*设置网格间距(如 .grid-gap-15 表示 15px)gap: 15px;.grid-item-*定义网格项的位置(如 .grid-item-span-2 表示跨越 2 列)grid-column: span 2;11.5.响应式布局类类名用途示例(CSS).responsive响应式容器(结合媒体查询)@media (max-width: 768px) { ... }.mobile-hidden在移动端隐藏元素@media (max-width: 768px) { display: none; }.desktop-only仅在桌面端显示@media (min-width: 769px) { display: block; }.sm-*/.md-*/.lg-*不同屏幕尺寸的适配类(如 .sm-col-6 表示小屏幕下的 6 列)grid-template-columns: repeat(6, 1fr);11.6.定位相关类类名用途示例(CSS).relative设置 position: relativeposition: relative;.absolute设置 position: absoluteposition: absolute;.fixed设置 position: fixedposition: fixed;.sticky设置 position: stickyposition: sticky; top: 0;.z-index-*控制层叠顺序(如 .z-index-10)z-index: 10;11.7.实用工具类(Utility Classes)类名用途示例(CSS).m-0/.p-10设置外边距/内边距(如 .m-0 表示 margin: 0)margin: 0;.w-100/.h-50设置宽高(如 .w-100 表示 width: 100%)width: 100%;.text-center文本居中text-align: center;.bg-primary背景色(需配合 CSS 变量)background: var(--primary);.overflow-hidden隐藏溢出内容overflow: hidden;12.重置默认样式12.1.快速重置(通用方法)通过通配符选择器 * 重置所有元素的 margin 和 padding,并统一盒模型:* { margin: 0; padding: 0; box-sizing: border-box; /* 统一盒模型为 border-box */ } html, body { width: 100%; height: 100%; }优点:简单快捷。缺点:可能过度重置(如列表、标题等元素的默认样式未被处理)。12.2.经典 Reset CSS(Eric Meyer 重置)更全面的重置方案,覆盖更多元素:/* Eric Meyer's Reset CSS */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; }优点:覆盖更多默认样式,适合复杂项目。缺点:可能移除一些有用样式(如标题的加粗、列表符号)。12.3.现代重置(Normalize.css)Normalize.css 是一个更温和的重置方案,保留有用的默认样式,同时修复浏览器兼容性问题。使用方法:直接通过 CDN 引入:<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">优点:平衡了跨浏览器一致性和保留默认样式。缺点:需额外引入外部文件。12.4.选择性重置(按需调整)根据项目需求,仅重置部分元素:/* 重置 body、标题、段落、列表 */ body, h1, h2, h3, h4, h5, h6, p, ul, ol, li { margin: 0; padding: 0; } /* 重置链接默认样式 */ a { text-decoration: none; color: inherit; } /* 重置表格默认样式 */ table { border-collapse: collapse; border-spacing: 0; }优点:灵活控制,减少不必要的重置。缺点:需手动维护。12.5.结合 CSS 变量(现代实践)在重置基础上定义全局变量,方便后续统一调整::root { --font-family: 'Arial', sans-serif; --spacing-unit: 8px; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: var(--font-family); } body { line-height: 1.5; padding: calc(var(--spacing-unit) * 2); }13.CSS3特性13.1.布局与盒模型13.1.1. Flexbox 弹性布局属性作用与常用值示例display定义弹性容器:flex(块级)、inline-flex(行内)display: flex;flex-direction主轴方向:row(默认)、column(垂直)、row-reverse、column-reverseflex-direction: column;justify-content主轴对齐:flex-start、center、space-between、space-aroundjustify-content: space-between;align-items交叉轴对齐:stretch(默认)、center、flex-startalign-items: center;flex-wrap换行方式:nowrap(默认)、wrap、wrap-reverseflex-wrap: wrap;完整示例:.container { display: flex; flex-direction: row; justify-content: center; align-items: center; gap: 10px; /* 子项间距 */ }13.1.2. Grid 网格布局属性作用与常用值示例display定义网格容器:grid、inline-griddisplay: grid;grid-template-columns列定义:repeat(3, 1fr)(等宽三列)、100px auto 20%grid-template-columns: 1fr 2fr;grid-template-rows行定义:100px minmax(200px, auto)grid-template-rows: 100px auto;gap网格间距:10px(行列统一)、10px 20px(行 10px,列 20px)gap: 20px;grid-area子项定位:grid-row: 1/3; grid-column: 2/4;见下方示例完整示例:.container { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: 100px auto; gap: 10px; } .item { grid-column: 1 / 3; /* 跨两列 */ grid-row: 1; }13.2、选择器与伪类13.2.1. 属性选择器选择器匹配规则示例[attr]包含指定属性的元素input[required](选择必填输入框)[attr="value"]属性值完全匹配a[target="_blank"](新窗口打开的链接)[attr^="value"]属性值以 value 开头a[href^="https"](选择 HTTPS 链接)[attr$="value"]属性值以 value 结尾img[src$=".png"](选择 PNG 图片)[attr*="value"]属性值包含 value 子字符串div[class*="box"](类名含 "box" 的 div)13.2. 伪类与伪元素选择器作用示例:nth-child(n)选择第 n 个子元素li:nth-child(2n)(偶数行列表项):hover鼠标悬停状态button:hover { background: #eee; }:focus输入框聚焦状态input:focus { border-color: blue; }::before/::after插入内容到元素前/后.tip::before { content: "⚠️ "; }13.3.动画与过渡13.3.1 Transition 过渡属性作用示例transition-property指定过渡属性(如 all、opacity)transition-property: transform;transition-duration过渡持续时间(单位:s 或 ms)transition-duration: 0.3s;transition-timing-function速度曲线:ease(默认)、linear、cubic-bezier()transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);简写transition: property duration timing-function delay;transition: all 0.3s ease;13.3.2. Animation 动画属性作用示例@keyframes定义动画关键帧`@keyframes slide { from { transform: translateX(-100%); } to { transform: translateX(0); } }`animation-name指定动画名称animation-name: slide;animation-duration动画持续时间animation-duration: 1s;animation-iteration-count播放次数:infinite(循环)、2(固定次数)animation-iteration-count: infinite;简写animation: name duration timing-function delay iteration-count direction;animation: slide 1s ease infinite;13.4.视觉效果13.4.1. 变形(Transform)属性作用示例translate()平移:translateX(50px)、translateY(20%)transform: translate(10px, -50%);rotate()旋转:rotate(45deg)(顺时针)、rotate(-90deg)transform: rotate(45deg);scale()缩放:scale(1.2)(放大 1.2 倍)transform: scale(0.8);skew()倾斜:skew(20deg, 10deg)transform: skew(15deg);13.4.2. 渐变与阴影属性作用示例linear-gradient()线性渐变background: linear-gradient(45deg, #ff6b6b, #4ecdc4);box-shadow盒子阴影:水平偏移 垂直偏移 模糊半径 颜色box-shadow: 2px 2px 10px rgba(0,0,0,0.1);text-shadow文字阴影text-shadow: 1px 1px 2px #000;13.5.响应式设计13.5.1. 媒体查询(Media Queries)/* 手机端样式 */ @media (max-width: 600px) { .container { flex-direction: column; } } /* 深色模式 */ @media (prefers-color-scheme: dark) { body { background: #333; color: white; } }13.5.2. 视口单位单位说明示例vw视口宽度的 1%(Viewport Width)width: 100vw;(铺满屏幕宽度)vh视口高度的 1%(Viewport Height)height: 50vh;(视口高度的一半)vmin/vmax取视口宽高中较小/较大值的 1%font-size: 4vmin;(适应移动端)13.6.性能优化硬件加速:.element { transform: translateZ(0); /* 触发 GPU 加速 */ }减少重绘: 使用 transform 和 opacity 做动画(避免修改 width、margin)。CSS 压缩: 使用工具(如 PostCSS、cssnano)压缩生产环境代码。13.7.兼容性处理前缀适配:.element { -webkit-transition: all 0.3s; /* Chrome/Safari */ -moz-transition: all 0.3s; /* Firefox */ transition: all 0.3s; }特性检测:@supports 判断浏览器是否支持某特性:@supports (display: grid) { .container { display: grid; } }14.BFCBFC(Block Formatting Context,块级格式化上下文)是 CSS 渲染中的一个独立布局环境。它规定了内部块级元素的排列规则,且 BFC 内外的元素互不影响。14.1.触发 BFC 的条件满足以下任一条件即可触发 BFC:根元素(<html>)。浮动元素:float 值不为 none。绝对定位元素:position 为 absolute 或 fixed。非块级容器:display 为 inline-block、table-cell、flex 等。Overflow 属性:overflow 值不为 visible(如 auto、hidden)。CSS3 新属性:display: flow-root(无副作用的 BFC 触发方式)。14.2.BFC 的核心作用防止外边距合并(Margin Collapse)问题:相邻块级元素的上下外边距会合并(取最大值)。解决:将其中一个元素包裹在 BFC 容器中。<div style="overflow: auto;"> <div style="margin: 20px;">内容</div> </div>包含浮动元素问题:父元素高度塌陷(子元素浮动后父元素高度为 0)。解决:父元素触发 BFC,自动计算浮动元素高度。.parent { overflow: auto; /* 触发 BFC */ } .child { float: left; }阻止元素被浮动覆盖问题:非浮动元素与浮动元素重叠。解决:非浮动元素触发 BFC,独占一行。.non-float { overflow: hidden; /* 触发 BFC */ }14.3.BFC 应用场景清除浮动<div class="parent" style="overflow: auto;"> <div class="child" style="float: left;"></div> </div>2. 自适应两栏布局<div style="float: left; width: 200px;">左栏</div> <div style="overflow: hidden;">右栏(自适应宽度)</div>3. 避免外边距穿透<div style="overflow: auto;"> <div style="margin-top: 50px;">内部元素</div> </div> <div>外部元素</div> <!-- 外边距不再合并 -->14.4.最佳实践优先使用 display: flow-root:无副作用(如滚动条),专为触发 BFC 设计。.container { display: flow-root; }避免滥用 overflow: hidden:可能导致内容被裁剪或意外滚动条。
2023年05月01日
121 阅读
0 评论
0 点赞