ECMAScript(ES6、ES7、ES8、ES9、ES10、ES11) 版本新特性概述

前言

ECMAScript 是一种由 Ecma 国际组织(前身为欧洲计算机制造商协会)标准化的脚本语言,它在 Web 开发中扮演着重要的角色。自 ECMAScript 5(简称 ES5)以来,每一年都会推出新的版本。ES6、ES7、ES8、ES9、ES10 和 ES11 中都有许多令人兴奋的新特性。本文将会介绍每个版本的主要新特性。

ECMAScript 6(ES6)

块级作用域变量声明 letconst

ES6 引入了 letconst 这两个新的关键字,它们使得 JavaScript 有了真正的块级作用域。let 声明的变量只在当前代码块内有效,而 const 定义的是常量,它通常被用于声明不会改变的变量。

// ES5
var a = 1;
if (a) {
  var b = 2;
}
console.log(b); // 2

// ES6
let c = 1;
if (c) {
  let d = 2;
}
console.log(d); // ReferenceError: d is not defined

const e = 1;
e = 2; // TypeError: Assignment to constant variable.

模板字符串

ES6 引入了一种新的字符串格式,称为模板字符串。它使用反引号 `` 括起来,其中可以包含表达式${expression},表达式的值会被自动计算并插入到字符串中。

// ES5
var name = 'Alice';
var url = 'https://example.com/' + name;

// ES6
let name = 'Alice';
let url = `https://example.com/${name}`;

解构赋值

解构赋值可以方便地从数组或对象中获取值并赋值给变量。

// ES5
var arr = [1, 2, 3];
var x = arr[0];
var y = arr[1];
var z = arr[2];

// ES6
let [x, y, z] = [1, 2, 3];

// 对象的解构赋值
let person = {name: 'Alice', age: 18};
let {name: pname, age: page} = person;
console.log(pname, page); // Alice 18

箭头函数

箭头函数是一种新的函数表达式语法,它比传统的函数表达式更简洁。

// ES5
var sum = function(a, b) {
  return a + b;
}

// ES6
let sum = (a, b) => a + b;

ES6 引入了一种新的语法用于定义类,它更加易读易写。

// ES5
var Person = function(name) {
  this.name = name;
}
Person.prototype.sayHello = function() {
  console.log('Hello, ' + this.name);
}

// ES6
class Person {
  constructor(name) {
    this.name = name;
  }
  sayHello() {
    console.log(`Hello, ${this.name}`);
  }
}

模块

ES6 引入了一种新的文件级别的模块定义语法,它使得 JavaScript 的模块化开发更加简单和可维护。

// 导出变量
export const PI = 3.141592653589793;
// 导出函数
export function square(x) {
  return x * x;
}
// 导出类
export class Circle {
  constructor(radius) {
    this.radius = radius;
  }
  area() {
    return PI * this.radius * this.radius;
  }
}
// 导入模块
import {PI, square, Circle} from './math';
console.log(PI); // 3.141592653589793
console.log(square(2)); // 4
console.log(new Circle(1).area()); // 3.141592653589793

ECMAScript 7(ES7)

Array.prototype.includes

Array.prototype.includes 方法用于判断数组中是否包含某个元素。

let arr = [1, 2, 3];
console.log(arr.includes(2)); // true
console.log(arr.includes(4)); // false

指数运算符

ES7 引入了一个新的指数运算符 **,方便进行乘方运算。

let x = 2 ** 3; // x 等于 8

ECMAScript 8(ES8)

异步函数

异步函数是一种新的函数类型,在函数定义前面加上 async 就可以定义异步函数。

async function f() {
  let result = await something(); // 等待异步操作完成
  // ...
}

对象属性的展开

ES8 允许在对象字面量中使用省略符 来展开另一个对象的属性。

let obj1 = {x: 1, y: 2};
let obj2 = {z: 3, ...obj1};
console.log(obj2); // {z: 3, x: 1, y: 2}

字符串填充

ES8 引入了字符串的填充方法 padStart()padEnd(),它们可以用于为字符串添加前缀或后缀并保持其长度不变。

let str = 'foo';
console.log(str.padStart(5, '*')); // **foo
console.log(str.padEnd(5, '*')); // foo**

ECMAScript 9(ES9)

异步迭代器

ES9 允许对象实现异步迭代器,需要实现一个异步的 Symbol.asyncIterator 方法。

async function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function* generate() {
  yield 1;
  await sleep(1000);
  yield 2;
}

(async function() {
  for await (const value of generate()) {
    console.log(value);
  }
})();

对象扩展

ES9 引入了一些新的对象扩展语法,包括对象的spread(...)和剩余(...rest)操作符。

let obj1 = {a: 1, b: 2};
let obj2 = {...obj1, c: 3};
console.log(obj2); // {a: 1, b: 2, c: 3}

let {a, ...rest} = obj2;
console.log(rest); // {b: 2, c: 3}

Promise.prototype.finally

Promise.prototype.finally() 方法是一个无论Promise对象最后状态如何都会执行的函数。

let p = Promise.resolve('foo');
p.finally(() => console.log('finally'));

ECMAScript 10(ES10)

Array.prototype.flat()

Array.prototype.flat() 方法可用于将嵌套的数组展平为一维数组。

let arr1 = [1, [2], [3, [4]]];
console.log(arr1.flat()); // [1, 2, 3, [4]]

let arr2 = [1, [2], [3, [4]]];
console.log(arr2.flat(2)); // [1, 2, 3, 4]

Array.prototype.flatMap()

Array.prototype.flatMap() 方法可以像 Array.prototype.map() 一样对数组中的每个元素执行一个函数,并将所有结果展平为一维数组。

let arr = [1, 2, 3];
let result = arr.flatMap(x => [x * 2]);
console.log(result); // [2, 4, 6]

可选链语法

ES10 引入了可选链语法 ?.,用于简化访问对象中特定属性的行为。

let person = {
  firstName: 'John',
  lastName: 'Doe'
}

console.log(person?.middleName?.toLowerCase()); // undefined

ECMAScript 11(ES11)

String.prototype.replaceAll()

String.prototype.replaceAll() 方法可以替换字符串中所有匹配的子字符串。

let str = 'Hello, World!';
console.log(str.replaceAll('o', 'x')); // Hellx, Wxrld!

Promise.allSettled()

Promise.allSettled() 方法返回一个 Promise 对象,该 Promise 在所有的 Promise 解决之后才会解决,并且会收集所有 Promise 对象的结果。

let p1 = Promise.resolve(1);
let p2 = Promise.reject('error');
let p3 = Promise.resolve(3);

Promise.allSettled([p1, p2, p3]).then(results => {
  console.log(results);
});
// [{status: 'fulfilled', value: 1}, {status: 'rejected', reason: 'error'}, {status: 'fulfilled', value: 3}]

globalThis

在浏览器中,全局对象是 window,在 Node.js 中,全局对象是 global,在 web worker 中,全局对象是 self。ES11 引入了一个新的 globalThis 全局对象,它可以在不同的环境中访问全局作用域。

console.log(globalThis === window); // true in a browser environment
console.log(globalThis === global); // true in Node.js environment

总结

随着 ECMAScript 的不断进化,JavaScript 语言不断变得更加强大和灵活。我们应该跟进 ECMAScript 新版本的主要特性,来不断提升我们的开发效率和代码质量。以上是 ES6 到 ES11 的主要特性介绍,希望对大家有所帮助。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a4f0d5add4f0e0ffd4cf5f


纠错反馈