JavaScript 的記錄和元組:不可變數據結構的未來
JavaScript 即將迎來兩種新的不可變數據類型:記錄和元組。它們目前處於 TC39 標準審批流程的第 2 階段,還在不斷完善中,尚未在任何瀏覽器或運行時環境中可用,但預計在明年內就會有可用的實現版本。它們旨在解決開發者在使用數組和對象時面臨的一些棘手問題。
經驗豐富的 JavaScript 開發者都知道,盡可能使用 const
聲明變量是最佳實踐。它使變量變得不可變。值不能更改,因此您需要處理的問題更少。
不幸的是,const
只能使基本值不可變(字符串、數字、BigInt、布爾值、符號和未定義)。您不能重新賦值數組或對象,但它們包含的值和屬性可以修改。例如:
<code class="language-javascript">// 数组常量 const myArray = [1, 2, 3]; // 更改数组值 myArray[0] = 99; myArray.push(42); console.log(myArray); // [ 99, 2, 3, 42 ] myArray = 'change'; // 错误!</code>
對像也是如此:
<code class="language-javascript">// 对象常量 const myObj = { a: 1, b: 2, c: 3 }; // 更改对象属性 myObj.a = 99; myObj.d = 42; console.log(myObj); // { a: 99, b: 2, c: 3, d: 42 } myObj = 'change'; // 错误!</code>
Object.freeze()
方法可以提供幫助,但它只對對象的直接子屬性應用淺凍結:
<code class="language-javascript">const myObj = { a: 1, b: 2, c: { v: 3 } }; Object.freeze(myObj); myObj.a = 99; // 静默忽略 myObj.c.v = 99; // 可以正常工作 console.log(myObj); // { a: 1, b: 2, c: { v: 99 } }</code>
因此,很難保證函數不會有意或無意地更改數組或對像中保存的值。開發人員要么聽天由命,要么傳遞變量的克隆版本——(這也有其自身的挑戰)。
當開發人員嘗試進行看似合理的對像或數組比較時,可能會出現更多混亂:
<code class="language-javascript">const str = 'my string'; console.log(str === 'mystring'); // false const num = 123; console.log(num === 123); // true const arr = [1, 2, 3]; console.log(arr === [1, 2, 3]); // false const obj = { a: 1 }; console.log(obj === { a: 1 }); // false</code>
只有基本類型可以按值比較。對象和數組是按引用傳遞和比較的。只有當兩個變量指向內存中的同一項時,它們才相等:
<code class="language-javascript">const a = [1, 2]; const b = a; b.push(3); console.log(a === b); // true // 原始数组已更改 console.log(a); // [1, 2, 3]</code>
深度比較兩個對像或數組需要一個遞歸比較函數來依次評估每個值。即使那樣,您也可能會遇到日期或函數等類型的問題,這些類型可能以不同的方式存儲。
元組是深度不可變的類似數組的數據結構。它們實際上是複合基本類型,在普通數組語法前面使用 #
修飾符來標識:
<code class="language-javascript">// 数组常量 const myArray = [1, 2, 3]; // 更改数组值 myArray[0] = 99; myArray.push(42); console.log(myArray); // [ 99, 2, 3, 42 ] myArray = 'change'; // 错误!</code>
或者,新的 Tuple.from()
方法可以從數組創建一個元組:
<code class="language-javascript">// 对象常量 const myObj = { a: 1, b: 2, c: 3 }; // 更改对象属性 myObj.a = 99; myObj.d = 42; console.log(myObj); // { a: 99, b: 2, c: 3, d: 42 } myObj = 'change'; // 错误!</code>
與標準數組不同,元組必須滿足以下要求:
undefined
的空位。例如,#[1,,,4]
是無效的。 <code class="language-javascript">const myObj = { a: 1, b: 2, c: { v: 3 } }; Object.freeze(myObj); myObj.a = 99; // 静默忽略 myObj.c.v = 99; // 可以正常工作 console.log(myObj); // { a: 1, b: 2, c: { v: 99 } }</code>
由於元組是基本類型,因此可以按值與其他元組進行深度比較:
<code class="language-javascript">const str = 'my string'; console.log(str === 'mystring'); // false const num = 123; console.log(num === 123); // true const arr = [1, 2, 3]; console.log(arr === [1, 2, 3]); // false const obj = { a: 1 }; console.log(obj === { a: 1 }); // false</code>
請注意,如果元組包含單個值,則可以使用較寬鬆的 ==
運算符進行比較。例如:
<code class="language-javascript">const a = [1, 2]; const b = a; b.push(3); console.log(a === b); // true // 原始数组已更改 console.log(a); // [1, 2, 3]</code>
記錄是深度不可變的類似對象的數據結構。同樣,它們是複合基本類型,在普通對象語法前面使用 #
修飾符來標識:
<code class="language-javascript">// 新的元组 const t1 = #[1, 2, 3]; const t2 = #[1, 2, #[3, 4]];</code>
或者,新的 Record()
構造函數可以從對象創建一個記錄:
<code class="language-javascript">// 从数组创建新的元组 const t3 = Tuple.from([1, 2, 3]);</code>
或者 Record.fromEntries()
方法可以從一系列數組或元組鍵值對創建一個記錄:
<code class="language-javascript">const t4 = #[new Date()]; // 错误(设置一个对象) const t5 = #[1, 2, [3, 4]]; // 错误(设置一个数组)</code>
與標準對像不同,記錄必須滿足以下要求:
#{ Symbol(): 1 }
是無效的。 <code class="language-javascript">const t6 = #[1, 2]; console.log(t6 === #[1, 2]); // true</code>
記錄可以與其他記錄進行深度比較,並且屬性順序無關緊要:
<code class="language-javascript">const t7 = #[99]; console.log(t7 == #[99]); // true console.log(t7 == 99); // true console.log(t7 == '99'); // true // 元组不能与数组比较 console.log(t7 == [99]); // false</code>
記錄只能與其他記錄進行比較,因此使用 ==
或 ===
運算符沒有區別。但是,可以提取 Object.keys()
和 Object.values()
用於特定比較。例如:
<code class="language-javascript">// 新的记录 const r1 = #{ a: 1, b: 2 }; const r2 = #{ a: 1, b: #{ c: 2 }, // 子记录 d: #[3, 4] // 子元组 };</code>
元組和記錄聽起來像是複雜計算機科學術語,但它們最終允許在 JavaScript 中進行強大的不可變數據存儲和比較。
什麼是 JavaScript 中的記錄? JavaScript 中的記錄是 ECMAScript 2022 (ES12) 中引入的一種類似對象的結構。它旨在表示具有命名屬性的數據,並且默認情況下是不可變的,因此適合用作數據結構,其中值在創建後不會更改。
記錄與普通的 JavaScript 對像有何不同?與普通的對像不同,JavaScript 中的記錄默認情況下是不可變的,並且一旦設置,其屬性就不能修改。記錄的設計也更可預測,結構更嚴格,因此適合用作數據容器。
什麼是 JavaScript 中的元組? JavaScript 中的元組是一個有序的元素集合,其中每個元素可以是不同類型。元組是不可變的,並且長度固定,提供了一種表示和處理特定順序的固定數量值的方法。
記錄和元組如何增強代碼的可讀性和可維護性?記錄和元組可以通過提供更聲明性和結構化的方式來表示數據來增強代碼的可讀性。不可變性方面也有助於防止意外修改,從而提高代碼的可維護性。
使用記錄和元組時是否存在任何性能方面的考慮?記錄和元組作為不可變數據結構,在某些情況下可以提高性能。但是,必須考慮瀏覽器支持和具體的用例,因為性能影響可能會因 JavaScript 運行時的實現細節而異。
如何在沒有原生支持的環境中為記錄和元組提供 polyfill?截至我的上次更新,可以使用 polyfill 或轉譯器在沒有原生支持的環境中模擬記錄和元組。但是,建議隨時了解 JavaScript 標準和工具的更新,因為生態系統在不斷發展。
以上是記錄和元組:JavaScript的新不成熟的數據類型的詳細內容。更多資訊請關注PHP中文網其他相關文章!