JavaScript 不斷發展,隨著 ES13 (ECMAScript 2022) 的引入,開發人員應該了解一些新功能,以便編寫更有效率、更現代的程式碼。在本文中,我們將深入探討 ES13 中十個最具影響力的功能,這些功能可以改善您的開發工作流程。
以前,您只能在非同步函數中使用await。這意味著如果您需要使用await,則必須將程式碼包裝在非同步函數中,即使模組的其餘部分不需要它。
// Without top-level await (Before ES13) async function fetchData() { const data = await fetch('/api/data'); return data.json(); } fetchData().then(console.log);
使用 ES13,您現在可以在模組的頂層使用 wait,從而無需額外的非同步包裝函數。
// With top-level await (ES13) const data = await fetch('/api/data'); console.log(await data.json());
在 ES13 之前,JavaScript 類別沒有真正的私有欄位或方法。開發人員經常使用下劃線或閉包等命名約定來模擬隱私,但這些方法並不是真正的隱私。
// Simulating private fields (Before ES13) class Person { constructor(name) { this._name = name; // Conventionally "private" } _getName() { return this._name; } greet() { return `Hello, ${this._getName()}!`; } } const john = new Person('John'); console.log(john._getName()); // Accessible, but intended to be private
ES13 引入了真正的私有實例方法和使用 # 前綴的存取器,確保它們無法在類別外部存取。
// Private instance methods and fields (ES13) class Person { #name = ''; constructor(name) { this.#name = name; } #getName() { return this.#name; } greet() { return `Hello, ${this.#getName()}!`; } } const john = new Person('John'); console.log(john.greet()); // Hello, John! console.log(john.#getName()); // Error: Private field '#getName' must be declared in an enclosing class
在 ES13 之前,靜態欄位和方法通常在類體之外定義,導致程式碼內聚力較差。
// Static fields outside class body (Before ES13) class MathUtilities {} MathUtilities.PI = 3.14159; MathUtilities.calculateCircumference = function(radius) { return 2 * MathUtilities.PI * radius; }; console.log(MathUtilities.PI); // 3.14159 console.log(MathUtilities.calculateCircumference(5)); // 31.4159
ES13 可讓您直接在類別體內定義靜態欄位和方法,從而提高可讀性和組織性。
// Static fields and methods inside class body (ES13) class MathUtilities { static PI = 3.14159; static calculateCircumference(radius) { return 2 * MathUtilities.PI * radius; } } console.log(MathUtilities.PI); // 3.14159 console.log(MathUtilities.calculateCircumference(5)); // 31.4159
邏輯運算子(&&、||、??)和賦值通常在詳細語句中手動組合,導致程式碼更加複雜。
// Manually combining logical operators and assignment (Before ES13) let a = 1; let b = 0; a = a && 2; // a = 2 b = b || 3; // b = 3 let c = null; c = c ?? 4; // c = 4 console.log(a, b, c); // 2, 3, 4
ES13 引入了邏輯賦值運算符,它以簡潔的語法將邏輯運算與賦值結合。
// Logical assignment operators (ES13) let a = 1; let b = 0; a &&= 2; // a = a && 2; // a = 2 b ||= 3; // b = b || 3; // b = 3 let c = null; c ??= 4; // c = c ?? 4; // c = 4 console.log(a, b, c); // 2, 3, 4
JavaScript 本身不支援弱引用和終結器,這使得在某些情況下管理資源變得困難,尤其是處理昂貴物件的大型應用程式。
// No native support for weak references (Before ES13) // Developers often had to rely on complex workarounds or external libraries.
ES13 引入了 WeakRef 和 FinalizationRegistry,為弱引用和垃圾回收後的清理任務提供原生支援。
// WeakRefs and FinalizationRegistry (ES13) let obj = { name: 'John' }; const weakRef = new WeakRef(obj); console.log(weakRef.deref()?.name); // 'John' obj = null; // obj is eligible for garbage collection setTimeout(() => { console.log(weakRef.deref()?.name); // undefined (if garbage collected) }, 1000); const registry = new FinalizationRegistry((heldValue) => { console.log(`Cleanup: ${heldValue}`); }); registry.register(obj, 'Object finalized');
檢查物件是否具有私有欄位並不簡單,因為私有欄位本身並不支援。開發人員必須依賴解決方法,例如檢查公共屬性或使用 instanceof 檢查。
// Checking for private fields using workarounds (Before ES13) class Car { constructor() { this.engineStarted = false; // Public field } startEngine() { this.engineStarted = true; } static isCar(obj) { return obj instanceof Car; // Not reliable for truly private fields } } const myCar = new Car(); console.log(Car.isCar(myCar)); // true
使用 ES13,您現在可以使用 # 語法直接檢查物件是否具有私有字段,使其更簡單、更可靠。
// Ergonomic brand checks for private fields (ES13) class Car { #engineStarted = false; startEngine() { this.#engineStarted = true; } static isCar(obj) { return #engineStarted in obj; } } const myCar = new Car(); console.log(Car.isCar(myCar)); // true
使用索引的括號表示法存取陣列中的元素,對於負索引,您必須手動計算位置。
// Accessing array elements (Before ES13) const arr = [1, 2, 3, 4, 5]; console.log(arr[arr.length - 1]); // 5 (last element)
at() 方法可讓您更直觀地使用正索引和負索引存取陣列元素。
// Accessing array elements with `at()` (ES13) const arr = [1, 2, 3, 4, 5]; console.log(arr.at(-1)); // 5 (last element) console.log(arr.at(0)); // 1 (first element)
要檢查物件是否有自己的屬性(不是繼承的),開發人員通常使用 Object.prototype.hasOwnProperty.call() 或 obj.hasOwnProperty()。
// Checking own properties (Before ES13) const obj = { a: 1 }; console.log(Object.prototype.hasOwnProperty.call(obj, 'a')); // true console.log(obj.hasOwnProperty('a')); // true
新的 Object.hasOwn() 方法簡化了此檢查,提供了更簡潔和可讀的語法。
// Checking own properties with `Object.hasOwn()` (ES13) const obj = { a: 1 }; console.log(Object.hasOwn(obj, 'a')); // true
將鍵值對(例如,從 Map 或陣列)轉換為物件需要循環和手動建構。
// Creating an object from entries (Before ES13) const entries = [['name', 'John'], ['age', 30]]; const obj = {}; entries.forEach(([key, value]) => { obj[key] = value; }); console.log(obj); // { name: 'John', age: 30 }
Object.fromEntries() simplifies the creation of objects from key-value pairs.
// Creating an object with `Object.fromEntries()` (ES13) const entries = [['name', 'John'], ['age', 30]]; const obj = Object.fromEntries(entries); console.log(obj); // { name: 'John', age: 30 }
The value of this in the top level of a module was undefined, leading to confusion when porting code from scripts to modules.
// Global `this` (Before ES13) console.log(this); // undefined in modules, global object in scripts
ES13 clarifies that the value of this at the top level of a module is always undefined, providing consistency between modules and scripts.
// Global `this` in modules (ES13) console.log(this); // undefined
These ES13 features are designed to make your JavaScript code more efficient, readable, and maintainable. By integrating these into your development practices, you can leverage the latest advancements in the language to build modern, performant applications.
以上是現代開發必須了解的 JavaScript ESFeatures的詳細內容。更多資訊請關注PHP中文網其他相關文章!