ES6 新特性详细讲解常见使用方式、场景与坑ES6ES2015是 JavaScript 历史上的一个巨大飞跃引入了大量现代开发中不可或缺的语法与 API。下面按类别逐一剖析核心特性重点说明日常怎么用、何时用、以及有哪些容易踩的坑。1.let和const基本讲解块级作用域变量只在当前{}内有效不再像var那样函数级作用域。let声明可变变量。const声明常量引用对于对象/数组内部属性可以改变只是不能重新赋值。常见使用方式与场景// 循环中使用 let 获得每次迭代独立的绑定for(leti0;i3;i){setTimeout(()console.log(i));// 0, 1, 2}// 若使用 var 会全部输出 3// 用 const 声明不会被重新赋值的引用增强代码可读性constconfig{api:/v1};config.api/v2;// OK属性可以改// config {}; // 报错Assignment to constant variable场景全面替代var优先使用const只在明确需要重新赋值时用let。⚠️ 常见坑暂时性死区TDZ声明前访问变量会报ReferenceError而不是undefined。console.log(a);// ReferenceErrorleta1;const声明的对象仍可被修改要完全冻结需用Object.freeze()。重复声明同一作用域内let/const不允许重复声明同名变量var可以。2. 箭头函数基本讲解箭头函数(){}没有自己的this、arguments、super或new.target它会捕获外层词法作用域的this。常见使用方式与场景// 简短回调[1,2,3].map(xx*2);// 保持 this 指向classFetcher{constructor(){this.datanull;}fetch(){fetch(/api).then(resres.json()).then(json{this.datajson;});// this 指向 Fetcher 实例}}// 立即返回对象字面量要加小括号constfnname({name});场景几乎所有的短回调、需要绑定外层this的异步处理、数组方法回调。⚠️ 常见坑没有自己的this在对象方法中直接使用箭头函数会导致this指向外层可能为window或undefined。constobj{name:test,say:()console.log(this.name)// this 指向全局无法获取 obj.name};obj.say();// undefined不能用作构造函数用new会抛出TypeError。没有arguments对象需用剩余参数...args替代。不适用于需要动态this的场景如 Vue 组件的methods或事件处理函数绑定。3. 模板字符串基本讲解使用反引号包裹支持多行字符串和${}插值还支持标签模板。常见使用方式与场景constnameWorld;conststrHello${name}!;// 多行字符串consthtmldiv p多行文字/p /div;// 标签模板如 styled-components, GraphQLfunctionhighlight(strings,...values){returnstrings.reduce((acc,str,i)${acc}${str}mark${values[i]||}/mark,);}highlightHello${name}, welcome!;// Hello markWorld/mark, welcome!场景拼接 HTML、URL、SQL 查询、国际化文本、任何需要插入变量或多行文本的地方。⚠️ 常见坑模板字符串内的空白和换行都会被保留可能导致意料之外的空格。标签模板的values数量与strings差 1需要小心处理边界。在${}里放复杂表达式注意可读性。4. 解构赋值基本讲解从数组或对象中按模式提取值并赋值给变量。数组解构let [a, b] [1, 2];对象解构let { x, y } { x: 1, y: 2 };支持重命名{ x: newX }和默认值{ x 10 }。常见使用方式与场景// 函数参数解构直观获取配置functionajax({url,methodGET,data{}}){/*...*/}// 交换变量[a,b][b,a];// 提取深层属性const{user:{profile:{email}}}response;场景提取接口返回数据、处理函数多个返回值、导入模块特定成员import { readFile } from fs。⚠️ 常见坑解构null或undefined会报错const{a}null;// TypeError: Cannot destructure property a of null建议对可能为空的数据设置默认空对象const { a } obj || {};。默认值只在值为undefined时生效null、false、0不会触发默认值。const{x10}{x:null};// x 是 null不是 10重命名与默认值同时使用时注意顺序const { a: newA 5 } obj;。5. 展开运算符Spread与剩余参数Rest基本讲解展开...iterable将数组/字符串等可迭代对象展开为元素序列。剩余参数...args将多个实参收集成一个数组代替arguments。常见使用方式与场景// 数组合并、浅拷贝constarr[1,2,3];constnewArr[0,...arr,4];// [0,1,2,3,4]constcopy[...arr];// 函数调用传参Math.max(...arr);// 剩余参数收集多余实参functionsum(...nums){returnnums.reduce((a,b)ab,0);}// 浅拷贝对象ES2018此处作为扩展constobjCopy{...originalObj};场景不可变数据操作、合并配置、函数参数灵活处理。⚠️ 常见坑展开只做浅拷贝嵌套对象/数组仍然是引用共享修改会互相影响。constorig{a:1,b:{c:2}};constcopy{...orig};copy.b.c3;console.log(orig.b.c);// 3被修改了剩余参数必须是最后一个形参function(a, ...rest, b){}会报错。...用于函数调用时若展开一个超大数据量数组可能导致参数过多引擎有参数数量限制。6. 函数默认参数基本讲解形参可以直接赋予默认值且默认表达式会在调用时惰性求值。常见使用方式与场景functionfetchData(url,methodGET,timeout5000){// ...}// 结合解构functioncreateElement({typediv,content}{}){// 防止传入 undefined 导致解构报错}场景提供函数可选参数的默认行为取代手动options options || {}那种假值覆盖问题。⚠️ 常见坑默认值只在参数为undefined时激活null、false、0不会触发。默认表达式作用域可以引用前面的参数但遵循 TDZ。functionf(xy,y1){}// 调用无参时 y 尚未初始化报 ReferenceError注意参数默认值会让函数产生一个独立的arguments行为在严格模式下arguments不会反映默认值参数的变化非严格模式有些差异建议直接用剩余参数。7. 类Class基本讲解语法糖基于原型继承实现提供了更清晰的构造函数、方法和extends、super。常见使用方式与场景classAnimal{constructor(name){this.namename;}speak(){console.log(${this.name}makes a noise.);}}classDogextendsAnimal{constructor(name,breed){super(name);// 必须在使用 this 前调用this.breedbreed;}speak(){console.log(${this.name}barks.);}}场景面向对象编程、React 类组件、封装复杂逻辑。⚠️ 常见坑必须使用new调用否则抛出TypeError。子类构造函数里super()必须且在使用this之前调用。类方法不可枚举enumerable: false与对象字面量方法不同。没有真正的私有属性ES6 标准中后续通过#语法或 TypeScriptprivate实现。ES6 中一般用_约定或Symbol/WeakMap模拟。箭头函数在类字段中类字段提案能绑定this但那是后续提案不是 ES6 的 class 本身。8. 模块ES Modules基本讲解通过import和export实现静态模块系统支持命名导出、默认导出以及重命名。常见使用方式与场景// math.jsexportconstPI3.14;exportfunctionadd(a,b){returnab;}exportdefaultfunctionmultiply(a,b){returna*b;}// app.jsimportmultiply,{PI,addassum}from./math.js;场景现代前端工程化、Node.js (type: module)、Tree-shaking 依赖分析。⚠️ 常见坑静态结构import和export只能在顶层作用域无法在条件语句中使用不能动态导入需用import()函数属 ES2020。只读绑定导入的变量是只读的尝试修改会报错但对象属性可修改。循环依赖如果 a 导入 bb 导入 a可能会导致拿到的导出是未初始化的需要重新设计模块或善用动态import()。路径必须完整浏览器环境下要加扩展名.jsNode 中根据配置。9. Promise基本讲解处理异步操作的状态机有三种状态pending、fulfilled、rejected。通过.then()/.catch()链式调用。常见使用方式与场景functionfetchUser(id){returnfetch(/users/${id}).then(resres.json());}fetchUser(1).then(userconsole.log(user)).catch(errconsole.error(失败,err)).finally(()console.log(请求结束));// finally ES2018// Promise 静态方法Promise.all([p1,p2])// 全部成功Promise.race([p1,p2])// 谁先完成Promise.resolve(value)Promise.reject(reason)场景网络请求、定时器、文件读取等所有异步操作且是 async/await 的基础。⚠️ 常见坑忘记return导致链断裂fetchUser(1).then(user{updateUI(user);// 没有 return 下一个 then 会收到 undefined}).then(data...);未处理拒绝未加.catch()的 Promise 一旦 reject可能产生UnhandledPromiseRejection错误需要全局兜底或必须 catch。then 的回调返回一个 Promise 会自动展开但同样要 return。Promise.all一个失败全部失败若需部分容错可用Promise.allSettledES2020或用.catch包裹单个请求。10. Set 与 Map基本讲解Set值唯一的集合支持add,has,delete,clear可迭代。Map键值对集合键可以是任意类型而对象键只能是字符串或 Symbol。支持set,get,has,delete可迭代。常见使用方式与场景// 数组去重constarr[1,2,2,3];constunique[...newSet(arr)];// Map 存储元数据用对象做键constcachenewMap();constobjKey{id:1};cache.set(objKey,data);cache.get(objKey);// data场景去重、缓存对象映射、记录访问状态、需要非字符串键的场景。⚠️ 常见坑Set 的比较是 SameValueZeroNaN视为等于自身0和-0相等。newSet([NaN,NaN]).size;// 1Map 的键基于引用比较对象作为键时即使内容相同但引用不同也会被视为不同键。若想用内容匹配需自行处理。WeakSet/WeakMap 只能存放对象且对键是弱引用不可迭代常用于 DOM 节点关联数据避免内存泄漏不能用于需要遍历的场景。11. Symbol基本讲解创建唯一且不可变的值常用作对象属性的标识符防止属性名冲突。Symbol()每次返回全新的值。常见使用方式与场景constLOG_LEVELSymbol(logLevel);constobj{[LOG_LEVEL]:debug,normalProp:hi};// for...in, Object.keys() 都不会枚举 Symbol 属性console.log(obj[LOG_LEVEL]);// debug场景定义内部状态、自定义迭代器Symbol.iterator、框架中避免属性冲突。⚠️ 常见坑Symbol 不能隐式转换成字符串constsSymbol(desc);s;// TypeError: Cannot convert a Symbol value to a string需使用String(s)或s.description。JSON.stringify 会忽略 Symbol 键和 Symbol 值。全局 Symbol 注册用Symbol.for(key)但可能造成全局污染。12. 迭代器Iterator与生成器Generator基本讲解迭代器协议对象实现next()方法返回{ value, done }。可迭代协议实现Symbol.iterator方法用于for...of、...展开等。生成器function*函数可通过yield暂停与恢复返回迭代器。常见使用方式与场景// 自定义迭代器constrange{from:1,to:5,[Symbol.iterator](){letcurrentthis.from;return{next:()currentthis.to?{value:current}:{done:true}};}};for(letnofrange){console.log(n);}// 生成器做 ID 生成function*idMaker(){letid0;while(true)yieldid;}constgenidMaker();gen.next().value;// 0场景处理惰性求值序列、实现异步流程控制redux-saga、自定义数据结构遍历。⚠️ 常见坑生成器返回的迭代器只能遍历一次。注意yield的返回值是下一个next(arg)传入的参数容易在双向通信时混淆。在生成器中未捕获的错误会使生成器终止。for…of 不能直接遍历普通对象除非实现迭代器必须迭代Object.keys/values/entries。13. Proxy 和 Reflect基本讲解Proxy创建对象的代理拦截并自定义对象的基本操作get、set、has、deleteProperty 等 13 种。Reflect提供操作对象的默认方法与 Proxy 陷阱一一对应使行为更可预测。常见使用方式与场景consthandler{get(target,key,receiver){console.log(Getting${key});returnReflect.get(target,key,receiver);},set(target,key,value,receiver){if(typeofvalue!number)thrownewError(必须为数字);returnReflect.set(target,key,value,receiver);}};constobjnewProxy({},handler);obj.a10;// 成功obj.bx;// 抛出错误场景数据验证、日志记录、响应式系统如 Vue 3 的 reactivity、属性访问控制、实现数组负索引等。⚠️ 常见坑代理会带来性能开销在热点代码中需谨慎。this 陷阱代理中的方法若依赖this可能指向代理而非原始对象需要绑定或使用receiver。无法拦截某些操作比如严格模式下某些操作、原型链上的 property 查找。应使用Reflect执行默认行为否则可能破坏内部原理。14. 新增数组与字符串方法常见新增Array:find,findIndex,fill,copyWithin,Array.from,Array.of,includes(ES7 但常与 ES6 共提)。String:startsWith,endsWith,includes,repeat,padStart/padEnd(后俩 ES2017)。使用方式与场景// 查找第一个符合条件的元素constusers[{id:1},{id:2}];constuserusers.find(uu.id2);// 填充数组newArray(3).fill(0);// [0,0,0]// 将类数组/迭代器转为真数组Array.from(document.querySelectorAll(li));// 字符串检测/api/users.startsWith(/api);场景替代indexOf ! -1的写法填充默认数据操作类数组。⚠️ 常见坑find返回第一个元素未找到返回undefinedfindIndex未找到返回-1。fill使用同一个引用填充对象数组导致所有元素共享同一个对象修改一个会影响全部constarrnewArray(3).fill({});arr[0].a1;console.log(arr[1].a);// 1全指向同一个对象Array.from对包含Symbol.iterator的对象转换更可靠普通有 length 属性的也能转但会缺失真正迭代。15. for…of 循环基本讲解遍历可迭代对象数组、字符串、Set、Map、arguments、NodeList 等获取的是值for...in获取键。使用与场景// 遍历 MapconstmapnewMap([[a,1],[b,2]]);for(let[key,value]ofmap){/* ... */}// 遍历字符串for(letcharofhello){}场景无需索引的数组遍历支持break/continue比forEach灵活。⚠️ 常见坑不能直接遍历纯对象因为普通对象没有实现迭代器协议会报错。可通过Object.entries(obj)等处理。在遍历过程中修改遍历集合会导致行为不一致建议先复制一份。总结与最佳实践变量声明默认const需要改则let忘记var。函数回调用箭头函数但对象方法和动态this场景用普通函数。异步Promise 链式调用记得return和catch更推荐async/await。解构/展开善用但注意浅拷贝问题深层修改用深拷贝库或手动解构。类组织复杂逻辑别忘super规则私有性可结合 TypeScript 或#语法。模块静态导入为主动态导入用于按需加载留意循环依赖。新数据结构用 Map/Set 处理键非字符串、去重等注意引用比较。掌握这些特性及其边界情况能大大提升代码简洁性、可读性和健壮性同时避开常见的开发陷阱。
ES6 新特性
ES6 新特性详细讲解常见使用方式、场景与坑ES6ES2015是 JavaScript 历史上的一个巨大飞跃引入了大量现代开发中不可或缺的语法与 API。下面按类别逐一剖析核心特性重点说明日常怎么用、何时用、以及有哪些容易踩的坑。1.let和const基本讲解块级作用域变量只在当前{}内有效不再像var那样函数级作用域。let声明可变变量。const声明常量引用对于对象/数组内部属性可以改变只是不能重新赋值。常见使用方式与场景// 循环中使用 let 获得每次迭代独立的绑定for(leti0;i3;i){setTimeout(()console.log(i));// 0, 1, 2}// 若使用 var 会全部输出 3// 用 const 声明不会被重新赋值的引用增强代码可读性constconfig{api:/v1};config.api/v2;// OK属性可以改// config {}; // 报错Assignment to constant variable场景全面替代var优先使用const只在明确需要重新赋值时用let。⚠️ 常见坑暂时性死区TDZ声明前访问变量会报ReferenceError而不是undefined。console.log(a);// ReferenceErrorleta1;const声明的对象仍可被修改要完全冻结需用Object.freeze()。重复声明同一作用域内let/const不允许重复声明同名变量var可以。2. 箭头函数基本讲解箭头函数(){}没有自己的this、arguments、super或new.target它会捕获外层词法作用域的this。常见使用方式与场景// 简短回调[1,2,3].map(xx*2);// 保持 this 指向classFetcher{constructor(){this.datanull;}fetch(){fetch(/api).then(resres.json()).then(json{this.datajson;});// this 指向 Fetcher 实例}}// 立即返回对象字面量要加小括号constfnname({name});场景几乎所有的短回调、需要绑定外层this的异步处理、数组方法回调。⚠️ 常见坑没有自己的this在对象方法中直接使用箭头函数会导致this指向外层可能为window或undefined。constobj{name:test,say:()console.log(this.name)// this 指向全局无法获取 obj.name};obj.say();// undefined不能用作构造函数用new会抛出TypeError。没有arguments对象需用剩余参数...args替代。不适用于需要动态this的场景如 Vue 组件的methods或事件处理函数绑定。3. 模板字符串基本讲解使用反引号包裹支持多行字符串和${}插值还支持标签模板。常见使用方式与场景constnameWorld;conststrHello${name}!;// 多行字符串consthtmldiv p多行文字/p /div;// 标签模板如 styled-components, GraphQLfunctionhighlight(strings,...values){returnstrings.reduce((acc,str,i)${acc}${str}mark${values[i]||}/mark,);}highlightHello${name}, welcome!;// Hello markWorld/mark, welcome!场景拼接 HTML、URL、SQL 查询、国际化文本、任何需要插入变量或多行文本的地方。⚠️ 常见坑模板字符串内的空白和换行都会被保留可能导致意料之外的空格。标签模板的values数量与strings差 1需要小心处理边界。在${}里放复杂表达式注意可读性。4. 解构赋值基本讲解从数组或对象中按模式提取值并赋值给变量。数组解构let [a, b] [1, 2];对象解构let { x, y } { x: 1, y: 2 };支持重命名{ x: newX }和默认值{ x 10 }。常见使用方式与场景// 函数参数解构直观获取配置functionajax({url,methodGET,data{}}){/*...*/}// 交换变量[a,b][b,a];// 提取深层属性const{user:{profile:{email}}}response;场景提取接口返回数据、处理函数多个返回值、导入模块特定成员import { readFile } from fs。⚠️ 常见坑解构null或undefined会报错const{a}null;// TypeError: Cannot destructure property a of null建议对可能为空的数据设置默认空对象const { a } obj || {};。默认值只在值为undefined时生效null、false、0不会触发默认值。const{x10}{x:null};// x 是 null不是 10重命名与默认值同时使用时注意顺序const { a: newA 5 } obj;。5. 展开运算符Spread与剩余参数Rest基本讲解展开...iterable将数组/字符串等可迭代对象展开为元素序列。剩余参数...args将多个实参收集成一个数组代替arguments。常见使用方式与场景// 数组合并、浅拷贝constarr[1,2,3];constnewArr[0,...arr,4];// [0,1,2,3,4]constcopy[...arr];// 函数调用传参Math.max(...arr);// 剩余参数收集多余实参functionsum(...nums){returnnums.reduce((a,b)ab,0);}// 浅拷贝对象ES2018此处作为扩展constobjCopy{...originalObj};场景不可变数据操作、合并配置、函数参数灵活处理。⚠️ 常见坑展开只做浅拷贝嵌套对象/数组仍然是引用共享修改会互相影响。constorig{a:1,b:{c:2}};constcopy{...orig};copy.b.c3;console.log(orig.b.c);// 3被修改了剩余参数必须是最后一个形参function(a, ...rest, b){}会报错。...用于函数调用时若展开一个超大数据量数组可能导致参数过多引擎有参数数量限制。6. 函数默认参数基本讲解形参可以直接赋予默认值且默认表达式会在调用时惰性求值。常见使用方式与场景functionfetchData(url,methodGET,timeout5000){// ...}// 结合解构functioncreateElement({typediv,content}{}){// 防止传入 undefined 导致解构报错}场景提供函数可选参数的默认行为取代手动options options || {}那种假值覆盖问题。⚠️ 常见坑默认值只在参数为undefined时激活null、false、0不会触发。默认表达式作用域可以引用前面的参数但遵循 TDZ。functionf(xy,y1){}// 调用无参时 y 尚未初始化报 ReferenceError注意参数默认值会让函数产生一个独立的arguments行为在严格模式下arguments不会反映默认值参数的变化非严格模式有些差异建议直接用剩余参数。7. 类Class基本讲解语法糖基于原型继承实现提供了更清晰的构造函数、方法和extends、super。常见使用方式与场景classAnimal{constructor(name){this.namename;}speak(){console.log(${this.name}makes a noise.);}}classDogextendsAnimal{constructor(name,breed){super(name);// 必须在使用 this 前调用this.breedbreed;}speak(){console.log(${this.name}barks.);}}场景面向对象编程、React 类组件、封装复杂逻辑。⚠️ 常见坑必须使用new调用否则抛出TypeError。子类构造函数里super()必须且在使用this之前调用。类方法不可枚举enumerable: false与对象字面量方法不同。没有真正的私有属性ES6 标准中后续通过#语法或 TypeScriptprivate实现。ES6 中一般用_约定或Symbol/WeakMap模拟。箭头函数在类字段中类字段提案能绑定this但那是后续提案不是 ES6 的 class 本身。8. 模块ES Modules基本讲解通过import和export实现静态模块系统支持命名导出、默认导出以及重命名。常见使用方式与场景// math.jsexportconstPI3.14;exportfunctionadd(a,b){returnab;}exportdefaultfunctionmultiply(a,b){returna*b;}// app.jsimportmultiply,{PI,addassum}from./math.js;场景现代前端工程化、Node.js (type: module)、Tree-shaking 依赖分析。⚠️ 常见坑静态结构import和export只能在顶层作用域无法在条件语句中使用不能动态导入需用import()函数属 ES2020。只读绑定导入的变量是只读的尝试修改会报错但对象属性可修改。循环依赖如果 a 导入 bb 导入 a可能会导致拿到的导出是未初始化的需要重新设计模块或善用动态import()。路径必须完整浏览器环境下要加扩展名.jsNode 中根据配置。9. Promise基本讲解处理异步操作的状态机有三种状态pending、fulfilled、rejected。通过.then()/.catch()链式调用。常见使用方式与场景functionfetchUser(id){returnfetch(/users/${id}).then(resres.json());}fetchUser(1).then(userconsole.log(user)).catch(errconsole.error(失败,err)).finally(()console.log(请求结束));// finally ES2018// Promise 静态方法Promise.all([p1,p2])// 全部成功Promise.race([p1,p2])// 谁先完成Promise.resolve(value)Promise.reject(reason)场景网络请求、定时器、文件读取等所有异步操作且是 async/await 的基础。⚠️ 常见坑忘记return导致链断裂fetchUser(1).then(user{updateUI(user);// 没有 return 下一个 then 会收到 undefined}).then(data...);未处理拒绝未加.catch()的 Promise 一旦 reject可能产生UnhandledPromiseRejection错误需要全局兜底或必须 catch。then 的回调返回一个 Promise 会自动展开但同样要 return。Promise.all一个失败全部失败若需部分容错可用Promise.allSettledES2020或用.catch包裹单个请求。10. Set 与 Map基本讲解Set值唯一的集合支持add,has,delete,clear可迭代。Map键值对集合键可以是任意类型而对象键只能是字符串或 Symbol。支持set,get,has,delete可迭代。常见使用方式与场景// 数组去重constarr[1,2,2,3];constunique[...newSet(arr)];// Map 存储元数据用对象做键constcachenewMap();constobjKey{id:1};cache.set(objKey,data);cache.get(objKey);// data场景去重、缓存对象映射、记录访问状态、需要非字符串键的场景。⚠️ 常见坑Set 的比较是 SameValueZeroNaN视为等于自身0和-0相等。newSet([NaN,NaN]).size;// 1Map 的键基于引用比较对象作为键时即使内容相同但引用不同也会被视为不同键。若想用内容匹配需自行处理。WeakSet/WeakMap 只能存放对象且对键是弱引用不可迭代常用于 DOM 节点关联数据避免内存泄漏不能用于需要遍历的场景。11. Symbol基本讲解创建唯一且不可变的值常用作对象属性的标识符防止属性名冲突。Symbol()每次返回全新的值。常见使用方式与场景constLOG_LEVELSymbol(logLevel);constobj{[LOG_LEVEL]:debug,normalProp:hi};// for...in, Object.keys() 都不会枚举 Symbol 属性console.log(obj[LOG_LEVEL]);// debug场景定义内部状态、自定义迭代器Symbol.iterator、框架中避免属性冲突。⚠️ 常见坑Symbol 不能隐式转换成字符串constsSymbol(desc);s;// TypeError: Cannot convert a Symbol value to a string需使用String(s)或s.description。JSON.stringify 会忽略 Symbol 键和 Symbol 值。全局 Symbol 注册用Symbol.for(key)但可能造成全局污染。12. 迭代器Iterator与生成器Generator基本讲解迭代器协议对象实现next()方法返回{ value, done }。可迭代协议实现Symbol.iterator方法用于for...of、...展开等。生成器function*函数可通过yield暂停与恢复返回迭代器。常见使用方式与场景// 自定义迭代器constrange{from:1,to:5,[Symbol.iterator](){letcurrentthis.from;return{next:()currentthis.to?{value:current}:{done:true}};}};for(letnofrange){console.log(n);}// 生成器做 ID 生成function*idMaker(){letid0;while(true)yieldid;}constgenidMaker();gen.next().value;// 0场景处理惰性求值序列、实现异步流程控制redux-saga、自定义数据结构遍历。⚠️ 常见坑生成器返回的迭代器只能遍历一次。注意yield的返回值是下一个next(arg)传入的参数容易在双向通信时混淆。在生成器中未捕获的错误会使生成器终止。for…of 不能直接遍历普通对象除非实现迭代器必须迭代Object.keys/values/entries。13. Proxy 和 Reflect基本讲解Proxy创建对象的代理拦截并自定义对象的基本操作get、set、has、deleteProperty 等 13 种。Reflect提供操作对象的默认方法与 Proxy 陷阱一一对应使行为更可预测。常见使用方式与场景consthandler{get(target,key,receiver){console.log(Getting${key});returnReflect.get(target,key,receiver);},set(target,key,value,receiver){if(typeofvalue!number)thrownewError(必须为数字);returnReflect.set(target,key,value,receiver);}};constobjnewProxy({},handler);obj.a10;// 成功obj.bx;// 抛出错误场景数据验证、日志记录、响应式系统如 Vue 3 的 reactivity、属性访问控制、实现数组负索引等。⚠️ 常见坑代理会带来性能开销在热点代码中需谨慎。this 陷阱代理中的方法若依赖this可能指向代理而非原始对象需要绑定或使用receiver。无法拦截某些操作比如严格模式下某些操作、原型链上的 property 查找。应使用Reflect执行默认行为否则可能破坏内部原理。14. 新增数组与字符串方法常见新增Array:find,findIndex,fill,copyWithin,Array.from,Array.of,includes(ES7 但常与 ES6 共提)。String:startsWith,endsWith,includes,repeat,padStart/padEnd(后俩 ES2017)。使用方式与场景// 查找第一个符合条件的元素constusers[{id:1},{id:2}];constuserusers.find(uu.id2);// 填充数组newArray(3).fill(0);// [0,0,0]// 将类数组/迭代器转为真数组Array.from(document.querySelectorAll(li));// 字符串检测/api/users.startsWith(/api);场景替代indexOf ! -1的写法填充默认数据操作类数组。⚠️ 常见坑find返回第一个元素未找到返回undefinedfindIndex未找到返回-1。fill使用同一个引用填充对象数组导致所有元素共享同一个对象修改一个会影响全部constarrnewArray(3).fill({});arr[0].a1;console.log(arr[1].a);// 1全指向同一个对象Array.from对包含Symbol.iterator的对象转换更可靠普通有 length 属性的也能转但会缺失真正迭代。15. for…of 循环基本讲解遍历可迭代对象数组、字符串、Set、Map、arguments、NodeList 等获取的是值for...in获取键。使用与场景// 遍历 MapconstmapnewMap([[a,1],[b,2]]);for(let[key,value]ofmap){/* ... */}// 遍历字符串for(letcharofhello){}场景无需索引的数组遍历支持break/continue比forEach灵活。⚠️ 常见坑不能直接遍历纯对象因为普通对象没有实现迭代器协议会报错。可通过Object.entries(obj)等处理。在遍历过程中修改遍历集合会导致行为不一致建议先复制一份。总结与最佳实践变量声明默认const需要改则let忘记var。函数回调用箭头函数但对象方法和动态this场景用普通函数。异步Promise 链式调用记得return和catch更推荐async/await。解构/展开善用但注意浅拷贝问题深层修改用深拷贝库或手动解构。类组织复杂逻辑别忘super规则私有性可结合 TypeScript 或#语法。模块静态导入为主动态导入用于按需加载留意循环依赖。新数据结构用 Map/Set 处理键非字符串、去重等注意引用比较。掌握这些特性及其边界情况能大大提升代码简洁性、可读性和健壮性同时避开常见的开发陷阱。