一、变量声明:let/const与var的核心区别
ES6新增let和const声明变量,解决了var的作用域与提升问题,三者核心差异如下:
1.1 核心区别对比
| 特性 | var | let | const |
|---|---|---|---|
| 变量提升 | 存在(提升后值为undefined) | 不存在(暂时性死区) | 不存在(暂时性死区) |
| 全局属性挂载 | 会挂载到window对象 | 不会挂载到window对象 | 不会挂载到window对象 |
| 重复声明 | 允许(覆盖原值) | 不允许(语法错误) | 不允许(语法错误) |
| 块级作用域 | 无(函数/全局作用域) | 有(包裹区域) | 有(包裹区域) |
| 重新赋值 | 允许 | 允许 | 不允许(指向不可变) |
| 初始值要求 | 可选 | 可选 | 必须(声明即赋值) |
1.2 关键注意点
const声明对象/数组时,仅限制“引用指向”不可变,对象内部属性/数组元素可修改;- 块级作用域应用:
for(let i=0;i<5;i++)可避免循环中异步操作的变量污染问题。
二、解构赋值:快速提取数据的高效语法
解构赋值用于快速从数组/对象中提取数据,简化变量赋值操作,核心应用场景如下:
2.1 数组解构
// 基础解构
const [a, b, c] = [10, 20, 30]; // a=10, b=20, c=30
// 跳过元素
const [x, , y] = [10, 20, 30]; // x=10, y=30
// 剩余元素(扩展运算符)
const [first, ...rest] = [10, 20, 30, 40]; // first=10, rest=[20,30,40]
// 默认值
const [m, n = 0] = [5]; // m=5, n=0
// 变量交换
let p = 1, q = 2;
[p, q] = [q, p]; // p=2, q=1
2.2 对象解构
// 基础解构(变量名与属性名一致)
const { id, name } = { id: 1, name: '小米', age: 10 }; // id=1, name='小米'
// 别名解构(避免变量冲突)
const age = 0;
const { age: age1 } = { id: 1, name: '小米', age: 10 }; // age1=10
// 默认值
const { sex = '未知' } = { id: 1, name: '小米' }; // sex='未知'
// 嵌套解构
const data = [{ id: 1, name: '珠峰' }, { id: 2, name: '珠峰' }];
data.forEach(item => {
const { id, name } = item || {};
console.log(id, name);
});
三、扩展运算符与剩余运算符
...符号在不同场景下分别作为扩展运算符或剩余运算符,核心用法如下:
3.1 扩展运算符(展开数据)
数组展开:用于数组克隆、合并或传递参数
// 数组克隆(浅克隆) const arr1 = [10, 20, 30]; const arr2 = [...arr1]; // arr2=[10,20,30], 与arr1互不影响(一级) // 数组合并 const arr3 = [...arr1, 40, 50]; // [10,20,30,40,50]对象展开:用于对象合并、属性覆盖
const obj1 = { a: 1 }; const obj2 = { ...obj1, b: 2 }; // { a:1, b:2 }
3.2 剩余运算符(收集数据)
- 函数参数:收集剩余参数为数组(替代arguments)
const fn = (n, ...m) => { console.log(n); // 第一个参数 console.log(m); // 剩余参数组成的数组 }; fn(10, 20, 30, 40); // n=10, m=[20,30,40]
四、数组新增方法与特性
ES6为数组新增多个实用方法,提升数据处理效率:
4.1 静态方法
Array.from():将类数组/Set集合转为数组const likeArr = document.querySelectorAll('div'); const arr = Array.from(likeArr); // 转为真正的数组Array.of():将一组值转为数组(修复new Array()的单参数缺陷)Array.of(1, 2, 3); // [1,2,3] Array.of(3); // [3](区别于new Array(3)生成长度为3的空数组)
4.2 实例方法
fill(value, start?, end?):填充数组元素new Array(3).fill(null); // [null, null, null]includes(value):判断数组是否包含指定值(支持NaN)[1, 2, NaN].includes(NaN); // true(区别于indexOf,indexOf(NaN)返回-1)flat(depth?):数组扁平化(默认深度为1)[1, [2, [3]]].flat(2); // [1,2,3]entries()/keys()/values():返回迭代器对象,用于遍历数组for (const [index, value] of [10, 20].entries()) { console.log(index, value); // 0 10; 1 20 }
五、新数据结构:Set与Map
ES6新增两种数据结构,解决传统数组/对象的局限性:
5.1 Set(无重复值的集合)
- 核心特性:成员唯一,支持迭代,适合数组去重
- 常用方法:
// 数组去重 const arr = [1, 1, 2, 3, 3]; const uniqueArr = [...new Set(arr)]; // [1,2,3] // 基本操作 const s = new Set(); s.add(1).add(2); // 添加元素 s.size; // 2(元素个数) s.has(1); // true(判断是否包含) s.delete(2); // true(删除元素) s.clear(); // 清空集合
5.2 Map(键可任意类型的键值对)
- 核心特性:键可设为对象/数组等类型(区别于对象键仅为字符串/Symbol)
- 常用方法:
const m = new Map(); const key = { x: 10 }; // 基本操作 m.set(key, 'value'); // 设置键值对(键为对象) m.get(key); // 'value'(获取值) m.size; // 1 m.has(key); // true m.delete(key); // true // 遍历 for (const [k, v] of m.entries()) { console.log(k, v); }
六、迭代器与生成器
6.1 迭代器(Iterator)
- 本质:一种接口,为数据结构提供统一遍历机制,支持
for...of循环 - 原生支持迭代器的数据结构:Array、String、Set、Map、NodeList等
- 自定义迭代器示例:
const banji = { name: '终极一班', stus: ['xiaoming', 'xiaoning', 'xiaotian'], [Symbol.iterator]() { let index = 0; return { next: () => { if (index < this.stus.length) { return { value: this.stus[index++], done: false }; } else { return { value: undefined, done: true }; } } }; } }; // for...of遍历自定义迭代器 for (const v of banji) { console.log(v); // xiaoming, xiaoning, xiaotian }
6.2 生成器(Generator)
本质:异步编程解决方案,通过
function*定义,yield分割代码执行核心用法:
// 基本用法 function* gen() { yield '第一步'; yield '第二步'; return '结束'; } const iterator = gen(); iterator.next(); // { value: '第一步', done: false } iterator.next(); // { value: '第二步', done: false } iterator.next(); // { value: '结束', done: true } // 带参数的生成器(next参数作为上一个yield的返回值) function* genWithParams(arg) { console.log(arg); // '初始参数' const one = yield '第一步'; console.log(one); // '参数1' const two = yield '第二步'; console.log(two); // '参数2' } const it = genWithParams('初始参数'); it.next(); it.next('参数1'); it.next('参数2');异步场景应用(模拟分步数据获取):
function getUsers() { setTimeout(() => iterator.next('用户数据'), 1000); } function* genAsync() { const users = yield getUsers(); console.log(users); // 1秒后输出'用户数据' } const iterator = genAsync(); iterator.next();
七、对象新增方法与特性
7.1 常用静态方法
| 方法 | 作用 | 示例 |
|---|---|---|
Object.assign(target, ...sources) | 合并对象(浅拷贝) | Object.assign({a:1}, {b:2}) → {a:1,b:2} |
Object.create(proto) | 创建新对象,指定原型 | Object.create({x:10}) → 新对象__proto__指向{x:10} |
Object.entries(obj) | 返回对象键值对数组 | Object.entries({a:1}) → [['a',1]] |
Object.is(a, b) | 精准比较两个值是否相等 | Object.is(NaN, NaN) → true |
Object.freeze(obj) | 冻结对象(禁止修改属性) | Object.freeze({a:1}) → 无法修改a的值 |
7.2 对象字面量增强
属性简写:属性名与变量名一致时可省略
const name = '小米'; const obj = { name }; // 等价于{ name: name }方法简写:省略
function关键字const obj = { sayHi() { console.log('hi'); } // 等价于sayHi: function(){} };
八、深浅克隆:对象/数组拷贝实现
8.1 浅克隆
- 定义:仅拷贝第一级数据,引用类型仍共享堆地址
- 实现方式:
Object.assign()- 扩展运算符(
[...arr]/{...obj}) - 数组
slice()/concat() - 自定义实现:
function cloneShallow(obj) { const target = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { target[key] = obj[key]; } } return target; }
8.2 深克隆
- 定义:递归拷贝所有层级数据,引用类型创建新堆地址,修改互不影响
- 实现方式:
JSON方法(局限性:不支持函数、正则、循环引用)
const deepCloneJSON = obj => JSON.parse(JSON.stringify(obj));自定义实现(支持复杂类型与循环引用):
function _type(obj) { return Object.prototype.toString.call(obj); } function deepClone(obj, map = new Map()) { // 处理null、基本类型、函数 if (obj === null || typeof obj !== 'object') return obj; // 处理循环引用 if (map.has(obj)) return map.get(obj); // 处理正则、日期 if (_type(obj) === '[object RegExp]') return new RegExp(obj); if (_type(obj) === '[object Date]') return new Date(obj); // 创建同类型实例 const target = new obj.constructor(); map.set(obj, target); // 缓存当前对象,解决循环引用 // 递归拷贝属性 for (const key in obj) { if (obj.hasOwnProperty(key)) { target[key] = deepClone(obj[key], map); } } return target; }
九、核心总结
- 变量声明:优先使用
let/const,避免var的作用域问题,const用于不可变引用; - 数据提取:解构赋值简化数组/对象数据提取,配合扩展/剩余运算符提升效率;
- 数据结构:Set适合去重,Map适合非字符串键场景,替代传统数组/对象;
- 异步编程:生成器是ES6异步解决方案,通过
yield分割代码,支持参数传递; - 对象操作:掌握新增静态方法,深浅克隆需根据场景选择,复杂场景用自定义深克隆(处理循环引用)。
要不要我帮你整理一份 ES6核心语法实战代码手册,包含所有知识点的可直接运行示例与面试高频考点标注?
