ECMAScript 2021,也被称为 ES12,是 JavaScript 的最新版本,于 2021 年 6 月发布。这个版本引入了许多新的特性和改进,其中最重要的是 Classes 和 Modules。这两个特性都是面向对象编程的重要组成部分,可以让开发者更轻松地创建可复用和可维护的代码。
Classes
Classes 是 ES6 引入的一个新特性,它可以让开发者更轻松地创建对象和类,并且可以继承和扩展已有的类。在 ES12 中,Classes 进一步改进了,引入了一些新的特性,下面我们来看一下。
Private Fields
在 ES12 中,Classes 支持私有字段(Private Fields)的定义。私有字段是指类中的成员变量,只能在类内部访问,外部无法访问。私有字段的定义使用 # 符号,如下所示:
// www.javascriptcn.com code example
class Person {
#name;
constructor(name) {
this.#name = name;
}
getName() {
return this.#name;
}
}
const person = new Person("Alice");
console.log(person.getName()); // 输出 "Alice"
console.log(person.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class在上面的代码中,我们定义了一个 Person 类,并在类中定义了一个私有字段 #name。在构造函数中,我们将传入的 name 参数赋值给私有字段 #name。然后,我们定义了一个 getName() 方法,用于获取私有字段 #name 的值。最后,我们创建了一个 Person 对象,并调用了 getName() 方法,输出了私有字段 #name 的值。
需要注意的是,私有字段只能在类内部访问,外部无法访问。如果我们尝试在外部访问私有字段 #name,会抛出 SyntaxError 异常。
Static Initialization Blocks
在 ES12 中,Classes 支持静态初始化块(Static Initialization Blocks)的定义。静态初始化块是指在类被加载时执行的代码块,用于初始化静态变量。静态变量是指类的成员变量,它们的值在类加载时被初始化,并且在整个程序运行期间保持不变。
静态初始化块的定义使用 static 关键字和 {} 符号,如下所示:
// www.javascriptcn.com code example
class Person {
static #names = [];
static {
Person.#names.push("Alice");
Person.#names.push("Bob");
Person.#names.push("Charlie");
}
static getNames() {
return Person.#names;
}
}
console.log(Person.getNames()); // 输出 ["Alice", "Bob", "Charlie"]在上面的代码中,我们定义了一个 Person 类,并在类中定义了一个静态变量 #names。然后,我们定义了一个静态初始化块,在块中向 #names 数组中添加了三个元素。最后,我们定义了一个 getNames() 方法,用于获取静态变量 #names 的值。在代码的最后,我们调用了 getNames() 方法,并输出了 #names 数组的值。
需要注意的是,静态初始化块只会在类被加载时执行一次,之后不会再执行。如果我们多次调用 getNames() 方法,会得到同样的结果。
Modules
Modules 是 ES6 引入的另一个新特性,它可以让开发者更轻松地组织和管理代码,并且可以实现代码的复用和共享。在 ES12 中,Modules 进一步改进了,引入了一些新的特性,下面我们来看一下。
Top-level await
在 ES12 中,Modules 支持顶层 await(Top-level await)的使用。顶层 await 是指在模块顶层使用 await 关键字,用于等待异步操作的完成。在 ES6 中,顶层 await 是不允许的,但在 ES12 中,它成为了合法的语法。
// www.javascriptcn.com code example
// module.js
export async function fetchData() {
const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
const data = await response.json();
return data;
}
// main.js
import { fetchData } from "./module.js";
async function main() {
const data = await fetchData();
console.log(data);
}
main();在上面的代码中,我们定义了一个 fetchData() 函数,用于获取 JSON 数据。然后,我们在 main.js 中导入 fetchData() 函数,并在 main() 函数中调用它,使用顶层 await 等待异步操作的完成。在代码的最后,我们调用 main() 函数,输出获取到的数据。
需要注意的是,顶层 await 只能在模块顶层使用,不能在函数内部使用。如果我们尝试在函数内部使用顶层 await,会抛出 SyntaxError 异常。
Dynamic Import
在 ES12 中,Modules 支持动态导入(Dynamic Import)的使用。动态导入是指在运行时动态加载模块,可以根据需要加载不同的模块。在 ES6 中,动态导入是不支持的,但在 ES12 中,它成为了合法的语法。
// main.js
async function main() {
const module = await import("./module.js");
const data = await module.fetchData();
console.log(data);
}
main();在上面的代码中,我们使用 import() 函数动态导入了 module.js 模块,并在获取到模块之后调用了 fetchData() 函数。在代码的最后,我们调用 main() 函数,输出获取到的数据。
需要注意的是,动态导入返回的是一个 Promise 对象。如果我们需要获取模块中的某个成员,需要使用 await 关键字等待 Promise 对象的完成。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d18efda941bf7134343847