ES6+ 新特性概览
总结 ES6 及后续版本的常用新特性
问题
总结 ES6+ 中常用的新特性,包括 Let/Const、箭头函数、Class、Proxy、Map/Set、Symbol、BigInt 等。
解答
Let 和 Const
// var 存在变量提升,let/const 有暂时性死区
console.log(a); // undefined
console.log(b); // ReferenceError
var a = 1;
let b = 2;
// let 允许重新赋值,const 不允许
let x = 1;
x = 2; // OK
const y = 1;
y = 2; // TypeError
// const 声明的对象,属性可以修改
const obj = { name: 'Tom' };
obj.name = 'Jerry'; // OK
obj = {}; // TypeError
// 块级作用域
{
let blockVar = 'inside';
var funcVar = 'outside';
}
console.log(funcVar); // 'outside'
console.log(blockVar); // ReferenceError
箭头函数
// 基本语法
const add = (a, b) => a + b;
const square = x => x * x;
const greet = () => 'Hello';
// 返回对象需要加括号
const createUser = name => ({ name, id: Date.now() });
// 箭头函数没有自己的 this,继承外层作用域
const obj = {
name: 'Tom',
// 普通函数:this 指向调用者
sayName() {
console.log(this.name); // 'Tom'
},
// 箭头函数:this 继承定义时的外层作用域
sayNameArrow: () => {
console.log(this.name); // undefined (this 指向全局)
},
// 常见用法:回调中保持 this
delayedSay() {
setTimeout(() => {
console.log(this.name); // 'Tom'
}, 100);
}
};
// 箭头函数没有 arguments
const fn = () => {
console.log(arguments); // ReferenceError
};
// 用 rest 参数代替
const fn2 = (...args) => {
console.log(args);
};
Class
// 类声明
class Animal {
// 静态属性
static kingdom = 'Animalia';
// 私有字段(ES2022)
#secret = 'private';
constructor(name) {
this.name = name;
}
// 实例方法
speak() {
console.log(`${this.name} makes a sound`);
}
// 静态方法
static create(name) {
return new Animal(name);
}
// getter/setter
get info() {
return `Animal: ${this.name}`;
}
set nickname(value) {
this.name = value;
}
}
// 继承
class Dog extends Animal {
constructor(name, breed) {
super(name); // 必须先调用 super
this.breed = breed;
}
speak() {
console.log(`${this.name} barks`);
}
}
const dog = new Dog('Buddy', 'Labrador');
dog.speak(); // 'Buddy barks'
console.log(Dog.kingdom); // 'Animalia'
Proxy
// 基本用法
const target = { name: 'Tom', age: 20 };
const proxy = new Proxy(target, {
// 拦截读取
get(target, prop, receiver) {
console.log(`Getting ${prop}`);
return Reflect.get(target, prop, receiver);
},
// 拦截设置
set(target, prop, value, receiver) {
console.log(`Setting ${prop} = ${value}`);
return Reflect.set(target, prop, value, receiver);
},
// 拦截 in 操作符
has(target, prop) {
return prop in target;
},
// 拦截删除
deleteProperty(target, prop) {
console.log(`Deleting ${prop}`);
return delete target[prop];
}
});
proxy.name; // 'Getting name'
proxy.age = 21; // 'Setting age = 21'
// 实际应用:数据验证
const validator = {
set(target, prop, value) {
if (prop === 'age' && typeof value !== 'number') {
throw new TypeError('Age must be a number');
}
target[prop] = value;
return true;
}
};
const person = new Proxy({}, validator);
person.age = 25; // OK
person.age = 'young'; // TypeError
Map 和 Set
// Map:键值对集合,键可以是任意类型
const map = new Map();
// 设置和获取
map.set('name', 'Tom');
map.set({ id: 1 }, 'object key');
map.set(function() {}, 'function key');
console.log(map.get('name')); // 'Tom'
console.log(map.size); // 3
// 初始化
const map2 = new Map([
['a', 1],
['b', 2]
]);
// 遍历
for (const [key, value] of map2) {
console.log(key, value);
}
map2.forEach((value, key) => console.log(key, value));
// 常用方法
map.has('name'); // true
map.delete('name');
map.clear();
// Set:值的集合,自动去重
const set = new Set([1, 2, 2, 3, 3, 3]);
console.log([...set]); // [1, 2, 3]
set.add(4);
set.has(4); // true
set.delete(4);
set.size; // 3
// 数组去重
const arr = [1, 1, 2, 2, 3];
const unique = [...new Set(arr)]; // [1, 2, 3]
// 集合运算
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
// 并集
const union = new Set([...a, ...b]); // {1, 2, 3, 4}
// 交集
const intersection = new Set([...a].filter(x => b.has(x))); // {2, 3}
// 差集
const difference = new Set([...a].filter(x => !b.has(x))); // {1}
WeakMap 和 WeakSet
// WeakMap:键必须是对象,键是弱引用
const wm = new WeakMap();
let obj = { name: 'Tom' };
wm.set(obj, 'metadata');
obj = null; // obj 可被垃圾回收,WeakMap 中的条目也会被清除
// 常见用途:存储私有数据
const privateData = new WeakMap();
class User {
constructor(name, password) {
this.name = name;
privateData.set(this, { password });
}
checkPassword(pwd) {
return privateData.get(this).password === pwd;
}
}
// WeakSet:值必须是对象,弱引用
const ws = new WeakSet();
let obj2 = {};
ws.add(obj2);
ws.has(obj2); // true
Symbol
// 创建唯一标识符
const s1 = Symbol('description');
const s2 = Symbol('description');
console.log(s1 === s2); // false
// 作为对象属性键
const KEY = Symbol('key');
const obj = {
[KEY]: 'secret value',
name: 'Tom'
};
console.log(obj[KEY]); // 'secret value'
console.log(Object.keys(obj)); // ['name'],Symbol 键不会被枚举
// 获取 Symbol 键
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(key)]
// 全局 Symbol 注册表
const globalSym = Symbol.for('shared');
const sameSym = Symbol.for('shared');
console.log(globalSym === sameSym); // true
console.log(Symbol.keyFor(globalSym)); // 'shared'
// 内置 Symbol
class MyArray {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
console.log([] instanceof MyArray); // true
// Symbol.iterator 定义迭代行为
const range = {
start: 1,
end: 5,
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
return {
next() {
if (current <= end) {
return { value: current++, done: false };
}
return { done: true };
}
};
}
};
console.log([...range]); // [1, 2, 3, 4, 5]
BigInt
// 创建 BigInt
const big1 = 9007199254740991n; // 字面量
const big2 = BigInt('9007199254740991'); // 构造函数
// 解决大整数精度问题
console.log(9007199254740991 + 2); // 9007199254740992(精度丢失)
console.log(9007199254740991n + 2n); // 9007199254740993n(正确)
// 运算
console.log(10n + 20n); // 30n
console.log(10n * 20n); // 200n
console.log(10n / 3n); // 3n(向下取整)
// 不能与普通数字混合运算
// 10n + 10; // TypeError
// 需要显式转换
console.log(10n + BigInt(10)); // 20n
console.log(Number(10n) + 10); // 20
// 比较可以混合
console.log(10n === 10); // false(类型不同)
console.log(10n == 10); // true
console.log(10n < 11); // true
其他常用特性
// 解构赋值
const [a, b, ...rest] = [1, 2, 3, 4];
const { name, age = 18 } = { name: 'Tom' };
// 展开运算符
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4];
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 };
// 模板字符串
const name = 'Tom';
const greeting = `Hello, ${name}!`;
// 可选链和空值合并
const user = { profile: { name: 'Tom' } };
const city = user?.address?.city ?? 'Unknown';
// Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('done'), 1000);
});
// async/await
async function fetchData() {
try {
const response = await fetch('/api/data');
return await response.json();
} catch (error) {
console.error(error);
}
}
// for...of
for (const item of [1, 2, 3]) {
console.log(item);
}
// 默认参数
function greet(name = 'Guest') {
return `Hello, ${name}`;
}
关键点
- let/const:块级作用域,暂时性死区,const 声明的引用类型属性可修改
- 箭头函数:没有自己的 this、arguments、prototype,不能用作构造函数
- Class:语法糖,本质还是原型继承,支持 extends、static、私有字段
- Proxy:拦截对象操作,配合 Reflect 使用,Vue 3 响应式原理
- Map/Set:Map 键可以是任意类型,Set 自动去重;Weak 版本是弱引用
- Symbol:创建唯一标识符,内置 Symbol 可自定义对象行为
- BigInt:处理大整数,不能与 Number 混合运算
目录