ES6(ES2015)新特性
发布时间:2015年6月 ES6(即 ES2015)是 JavaScript 历史上变化最大的一次升级,正式引入了块级作用域、类、模块、Promise、Generator、Proxy 等一整套现代语法与能力。
说明:本文件只保留 ES2015 正式特性,不混入 ES2016+ 才加入的能力(例如
Array.prototype.includes()、padStart()、Object.entries()、Promise.finally()、Array.prototype.flat()等)。
1. let 和 const
let
- 块级作用域,只在当前
{}内有效 - 不存在传统意义上的变量提升,存在暂时性死区(TDZ)
- 同一作用域内不能重复声明
{
let a = 10;
var b = 1;
}
console.log(b); // 1
console.log(a); // ReferenceError
const
- 用于声明常量,必须立即初始化
- 也是块级作用域
- 对于引用类型,地址不可变,但内容可以变
const PI = 3.14;
const arr = [1, 2, 3];
arr.push(4); // 允许
// arr = []; // TypeError
暂时性死区(TDZ)
{
// console.log(x); // ReferenceError
let x = 1;
}
2. 解构赋值(Destructuring)
数组解构
let [a, b, c] = [1, 2, 3];
let [x, , y] = [1, 2, 3];
let [m, ...n] = [1, 2, 3, 4];
console.log(a, b, c); // 1 2 3
console.log(x, y); // 1 3
console.log(n); // [2, 3, 4]
对象解构
let { name, age } = { name: '张三', age: 18 };
let { name: userName } = { name: '李四' };
console.log(name); // 张三
console.log(userName); // 李四
默认值
let [a = 1, b = 2] = [3];
let { x = 10, y = 20 } = { x: 5 };
console.log(a, b); // 3 2
console.log(x, y); // 5 20
函数参数解构
function greet({ name, age }) {
console.log(`你好,${name},今年 ${age} 岁`);
}
greet({ name: '王五', age: 20 });
3. 字符串扩展
模板字符串
支持换行、插值、表达式:
let name = '张三';
let age = 18;
let str = `你好,${name},明年 ${age + 1} 岁`;
console.log(str);
标签模板
function tag(strings, ...values) {
console.log(strings);
console.log(values);
}
let name = '张三';
let age = 18;
tag`姓名:${name},年龄:${age}`;
新方法
'hello'.includes('ell'); // true
'hello'.startsWith('he'); // true
'hello'.endsWith('lo'); // true
'hello'.repeat(3); // 'hellohellohello'
Unicode 增强
'𠮷'.length; // 2
'𠮷'.codePointAt(0); // 134071
String.fromCodePoint(134071); // '𠮷'
'\u{20BB7}'; // '𠮷'
String.raw()
String.raw`Hi\n${2 + 3}`;
// 'Hi\\n5'
4. 数值与 Math 扩展
二进制和八进制表示法
0b111110111 === 503; // true
0o767 === 503; // true
Number 新方法与常量
Number.isFinite(15); // true
Number.isNaN(NaN); // true
Number.isInteger(5); // true
Number.EPSILON; // 2.220446049250313e-16
Number.MAX_SAFE_INTEGER; // 9007199254740991
Number.MIN_SAFE_INTEGER; // -9007199254740991
Math 新方法
Math.trunc(4.9); // 4
Math.sign(-5); // -1
Math.cbrt(8); // 2
Math.hypot(3, 4); // 5
5. 函数扩展
默认参数
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello'); // Hello World
log('Hello', 'China'); // Hello China
rest 参数
function sum(...nums) {
return nums.reduce((total, item) => total + item, 0);
}
sum(1, 2, 3); // 6
箭头函数
const add = (a, b) => a + b;
const square = n => n * n;
const getObj = id => ({ id, name: 'test' });
注意:
- 箭头函数没有自己的
this - 没有
arguments - 不能当构造函数使用
const obj = {
id: 1,
normal() {
console.log(this.id);
},
arrow: () => {
console.log(this.id);
}
};
函数名 name 属性
function foo() {}
console.log(foo.name); // 'foo'
尾调用优化(规范层面)
尾调用是函数最后一步调用另一个函数。ES2015 在规范层面定义了相关优化空间,但实际引擎支持并不统一,因此开发中不要强依赖它。
6. 数组扩展
扩展运算符 ...
let arr1 = [1, 2];
let arr2 = [3, 4];
let arr3 = [...arr1, ...arr2];
function add(x, y) {
return x + y;
}
add(...[1, 2]); // 3
Array.from()
将类数组或可迭代对象转为真正数组:
Array.from({ length: 3 }, (_, i) => i); // [0, 1, 2]
Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
Array.of()
Array.of(1, 2, 3); // [1, 2, 3]
Array.of(3); // [3]
find() 和 findIndex()
[1, 2, 3, 4].find(x => x > 2); // 3
[1, 2, 3, 4].findIndex(x => x > 2); // 2
fill()
[1, 2, 3].fill(0); // [0, 0, 0]
[1, 2, 3].fill(0, 1, 2); // [1, 0, 3]
copyWithin()
复制数组内部指定位置的成员到其他位置:
[1, 2, 3, 4, 5].copyWithin(0, 3); // [4, 5, 3, 4, 5]
keys()、values()、entries()
let arr = ['a', 'b'];
for (let key of arr.keys()) {
console.log(key); // 0, 1
}
for (let value of arr.values()) {
console.log(value); // 'a', 'b'
}
for (let [index, value] of arr.entries()) {
console.log(index, value);
}
7. 对象扩展
属性简写
let name = '张三';
let age = 18;
let obj = { name, age };
属性名表达式
let key = 'name';
let obj = {
[key]: '张三'
};
方法简写
let obj = {
hello() {
return '你好';
}
};
Object.is()
Object.is(NaN, NaN); // true
Object.is(+0, -0); // false
NaN === NaN; // false
Object.assign()
let target = { a: 1 };
let source = { b: 2 };
let result = Object.assign(target, source);
console.log(result); // { a: 1, b: 2 }
Object.setPrototypeOf() / Object.getPrototypeOf()
let proto = { greet() { return 'hello'; } };
let obj = {};
Object.setPrototypeOf(obj, proto);
console.log(Object.getPrototypeOf(obj) === proto); // true
super 关键字(对象方法中)
let proto = {
foo() {
return 'hello';
}
};
let obj = {
foo() {
return super.foo() + ' world';
}
};
Object.setPrototypeOf(obj, proto);
obj.foo(); // 'hello world'
8. Symbol
表示独一无二的值,是第 7 种原始数据类型:
let s1 = Symbol('foo');
let s2 = Symbol('foo');
console.log(s1 === s2); // false
作为对象属性名
const id = Symbol('id');
let user = {
[id]: 1001,
name: '张三'
};
console.log(user[id]);
console.log(Object.getOwnPropertySymbols(user));
内置 Symbol
let arr = [1, 2, 3];
let iter = arr[Symbol.iterator]();
console.log(iter.next());
9. Set、Map、WeakSet、WeakMap
Set
值唯一的集合:
let set = new Set([1, 2, 2, 3]);
set.add(4);
set.delete(1);
set.has(2); // true
set.size; // 3
[...set]; // [2, 3, 4]
Map
键可以是任意类型:
let map = new Map();
map.set('name', '张三');
map.set(1, '数字键');
map.get('name'); // '张三'
map.has(1); // true
map.size; // 2
WeakSet / WeakMap
- 只能存对象(ES2015 语义下)
- 是弱引用,不阻止垃圾回收
- 不可遍历
let obj = {};
let weakMap = new WeakMap();
weakMap.set(obj, 'data');
let weakSet = new WeakSet();
weakSet.add(obj);
10. Proxy 和 Reflect
Proxy
可以拦截对象的读取、赋值、删除、函数调用等操作:
let obj = { name: '张三' };
let proxy = new Proxy(obj, {
get(target, key) {
return key in target ? target[key] : '不存在';
},
set(target, key, value) {
target[key] = value;
return true;
}
});
console.log(proxy.name); // 张三
console.log(proxy.age); // 不存在
proxy.age = 18;
Reflect
与 Proxy 拦截器一一对应,提供默认行为:
Reflect.get(obj, 'name');
Reflect.set(obj, 'age', 18);
Reflect.has(obj, 'name');
Reflect.deleteProperty(obj, 'name');
11. Promise
Promise 是 ES2015 正式引入的异步编程解决方案,用于解决回调地狱。
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('成功'), 1000);
});
promise
.then(res => {
console.log(res);
})
.catch(err => {
console.error(err);
});
常用静态方法
Promise.resolve(42);
Promise.reject(new Error('err'));
Promise.all([p1, p2, p3]);
Promise.race([p1, p2, p3]);
状态
pendingfulfilledrejected
12. Iterator 和 for...of
Iterator
任何实现了 next() 方法并返回 { value, done } 的对象,都可以被视为迭代器。
let arr = [1, 2, 3];
let iter = arr[Symbol.iterator]();
iter.next(); // { value: 1, done: false }
iter.next(); // { value: 2, done: false }
iter.next(); // { value: 3, done: false }
iter.next(); // { value: undefined, done: true }
for...of
用于遍历可迭代对象:
for (let val of [1, 2, 3]) {
console.log(val);
}
for (let [key, val] of new Map([['a', 1], ['b', 2]])) {
console.log(key, val);
}
13. Generator 生成器
Generator 是一种可以暂停和恢复执行的函数。
function* helloGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
let gen = helloGenerator();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
与 Iterator 的关系
Generator 函数执行后返回一个迭代器对象,因此它是生成迭代器的语法糖。
14. Class 类
ES6 提供了更清晰的类语法,本质仍然基于原型。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `我是 ${this.name},今年 ${this.age} 岁`;
}
static create(name) {
return new Person(name, 0);
}
}
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
greet() {
return `${super.greet()},读 ${this.grade} 年级`;
}
}
关键点
constructor是构造方法extends用于继承- 子类中必须先
super()再使用this static定义静态方法
15. 模块化(Module)
ES2015 正式定义了原生模块语法。
export 导出
export const name = '张三';
export function add(a, b) {
return a + b;
}
export default class Person {}
import 导入
import { name, add } from './module.js';
import Person from './module.js';
import * as mod from './module.js';
特点
- 静态分析友好
- 支持按需导出与导入
import会提升到模块顶部执行
16. 正则、二进制数组与其他补充
RegExp 扩展
ES2015 为正则引入了 u 和 y 标志:
/^.$/u.test('𠮷'); // true,正确识别 Unicode 字符
let r = /a/y;
r.lastIndex = 1;
r.exec('ba'); // ['a']
u:Unicode 模式y:粘连匹配,要求从lastIndex位置开始匹配
二进制数组(TypedArray)
let buffer = new ArrayBuffer(16);
let int32View = new Int32Array(buffer);
int32View[0] = 42;
console.log(int32View[0]); // 42
相关对象:
ArrayBuffer -> 原始二进制数据缓冲区
DataView -> 灵活读写二进制数据
TypedArray -> 各种类型化数组视图
new.target
可用于判断函数是否通过 new 调用:
function Person(name) {
if (!new.target) {
throw new Error('必须使用 new 调用');
}
this.name = name;
}
总结
| 模块 | 代表特性 |
|---|---|
| 变量声明 | let、const |
| 结构处理 | 解构赋值、模板字符串、展开运算符 |
| 函数能力 | 默认参数、rest、箭头函数 |
| 数据结构 | Set、Map、WeakSet、WeakMap、Symbol |
| 面向对象 | class、extends、super |
| 异步编程 | Promise |
| 元编程 | Proxy、Reflect |
| 遍历机制 | Iterator、for...of、Generator |
| 模块系统 | import、export |
| 底层能力 | TypedArray、RegExp u/y、new.target |
ES6(ES2015)奠定了现代 JavaScript 的基础。后续每年的 ECMAScript 更新,大多是在这套能力之上继续迭代和补充。