1. 引言
随着 JavaScript 语言的不断发展,ECMAScript 也不断更新,其中最新的版本为 ES12(也称为 ES2021)。ES6~ES12 为 JavaScript 带来了许多重要的新特性和功能,这些新特性极大地改善了语言的表达力和开发效率。在本篇文章中,我们将快速地了解 ES6~ES12 的全部特性。
2. ES6(2015)新特性
2.1 let 和 const 声明变量
ES6 为 JavaScript 引入了两个新的关键字 let 和 const 用来声明变量。let 和 const 声明的变量在代码块内有效,而 var 声明的变量在整个函数内有效。其中,let 声明的变量可以被重新赋值,而 const 声明的变量则不可被重新赋值。
// 使用 let 声明变量
let x = 5;
x = 6;
// 使用 const 声明常量
const y = 10;
注意:使用 const 声明的变量仍然可以被修改,但不能被重新赋值。
2.2 箭头函数
在 ES6 中,可以使用箭头函数来编写更简洁的函数表达式,这些函数具有更短的语法和更清晰的语义。箭头函数使用箭头(=>)语法定义。
// 使用箭头函数
const sum = (a, b) => a + b;
console.log(sum(2, 3)); // 输出 5
箭头函数有以下特点:
没有自己的 this,会捕获上下文的 this 值;
不可使用 arguments 对象,可以使用 rest parameters 来代替;
不能使用 yield 关键字。
2.3 模板字符串
ES6 引入了模板字符串,用于更方便地拼接字符串。模板字符串使用反引号(`)表示,字符串中可以包含变量、表达式以及换行符。
// 使用模板字符串
const name = 'Alice';
console.log(`Hello, ${name}!`);
2.4 解构(Destructuring)
ES6 引入了解构语法,可以从数组或对象中提取数据赋值给变量。
// 使用解构语法
const [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 输出 1 2 3
const { x, y, z } = { x: 1, y: 2, z: 3 };
console.log(x, y, z); // 输出 1 2 3
2.5 for...of 循环
ES6 引入了 for...of 循环,用于遍历具有迭代器(Iterator)接口的数据结构,如数组、Set 和 Map。
// 使用 for...of 循环
const arr = [1, 2, 3];
for (const item of arr) {
console.log(item);
}
2.6 Promise
ES6 引入了 Promise,用于更方便地处理异步操作。Promise 可以将异步操作封装成一个对象,可以更好地管理异步操作的状态和结果。
// 使用 Promise 处理异步操作
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
resolve('Done!');
}, 1000);
});
promise.then((result) => {
console.log(result); // 输出 Done!
});
2.7 扩展运算符(Spread Operator)
ES6 引入了扩展运算符,可以将一个数组或对象“展开”成多个参数传入函数或构造器中。
// 使用扩展运算符
const arr = [1, 2, 3];
const arr2 = [...arr, 4, 5, 6];
console.log(arr2); // 输出 [1, 2, 3, 4, 5, 6]
const obj = { x: 1, y: 2 };
const obj2 = { ...obj, z: 3 };
console.log(obj2); // 输出 {x: 1, y: 2, z: 3}
3. ES7(2016)新特性
3.1 includes 方法
ES7 引入了 includes 方法,用于判断一个数组是否包含某个值。
// 使用 includes 方法
const arr = [1, 2, 3];
console.log(arr.includes(2)); // 输出 true
4. ES8(2017)新特性
4.1 async/await
ES8 引入了 async/await,用于更方便地处理异步操作。async/await 是基于 Promise 的封装,可以让异步代码看起来像同步代码。
// 使用 async/await 处理异步操作
async function getData() {
const response = await fetch('/api/data');
const data = await response.json();
return data;
}
getData().then((result) => {
console.log(result);
});
5. ES9(2018)新特性
5.1 Rest/Spread 属性
ES9 引入了 Rest/Spread 属性,可以轻松地实现对象和数组的解构赋值。
// 使用 Rest/Spread 属性
const obj = { x: 1, y: 2, z: 3 };
const { x, ...rest } = obj;
console.log(x, rest); // 输出 1 { y: 2, z: 3 }
const arr = [1, 2, 3, 4, 5];
const [a, b, ...rest] = arr;
console.log(a, b, rest); // 输出 1 2 [3, 4, 5]
6. ES10(2019)新特性
6.1 可选链运算符
ES10 引入了可选链运算符(Optional Chaining Operator),用于安全地访问深层次的对象属性,避免因为某个属性不存在而导致的错误。
// 使用可选链运算符
const obj = { x: 1, y: { z: 2 } };
console.log(obj?.y?.z); // 输出 2
6.2 空值合并运算符
ES10 引入了空值合并运算符(Nullish Coalescing Operator),用于处理在值为 null 或 undefined 时的默认值问题。
// 使用空值合并运算符
const x = null;
const y = x ?? 'default';
console.log(y); // 输出 'default'
7. ES11(2020)新特性
7.1 可选 catch 绑定
ES11 引入了可选 catch 绑定,可以省略 catch 子句中的参数,避免因为未使用 catch 参数而导致的 ESLint 错误。
// 使用可选 catch 绑定
try {
// something
} catch {
// handle error
}
7.2 String.prototype.matchAll()
ES11 引入了 String.prototype.matchAll() 方法,用于更方便地匹配正则表达式。
// 使用 String.prototype.matchAll() 方法
const regex = /test/g;
const str = 'test1test2test3';
const matches = str.matchAll(regex);
for (const match of matches) {
console.log(match);
}
8. ES12(2021)新特性
8.1 Promise.any()
ES12 引入了 Promise.any() 方法,用于多个异步操作中只要有一个成功就返回结果。
// 使用 Promise.any() 方法
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Error');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Done');
}, 500);
});
Promise.any([promise1, promise2]).then((result) => {
console.log(result); // 输出 Done
});
8.2 数字分隔符
ES12 引入了数字分隔符(Numeric Separators),可以在数字之间加上下划线(_)隔开,以提高数字的可读性。
// 使用数字分隔符
const num1 = 123_456_789;
const num2 = 0b1010_0001_0010;
console.log(num1, num2); // 输出 123456789 4162
9. 结论
ES6~ES12 为 JavaScript 带来了许多新特性和功能,这些新特性极大地提高了语言的表达力和开发效率。在开发过程中,我们可以根据需要使用这些特性来编写更简洁、更高效、更可读的代码,并且可以充分发挥语言的优势。