首頁 >web前端 >js教程 >記錄和元組:JavaScript的新不成熟的數據類型

記錄和元組:JavaScript的新不成熟的數據類型

Christopher Nolan
Christopher Nolan原創
2025-02-12 08:25:09269瀏覽

Records and Tuples: JavaScript's New Immutable Data Types

JavaScript 的記錄和元組:不可變數據結構的未來

JavaScript 即將迎來兩種新的不可變數據類型:記錄和元組。它們目前處於 TC39 標準審批流程的第 2 階段,還在不斷完善中,尚未在任何瀏覽器或運行時環境中可用,但預計在明年內就會有可用的實現版本。它們旨在解決開發者在使用數組和對象時面臨的一些棘手問題。

關鍵要點

  • 記錄和元組是 JavaScript 中正在開發的新的不可變數據類型,預計在明年內可用。它們旨在解決開發者面臨的挑戰,例如確保函數不會有意或無意地更改數組或對像中保存的值。
  • 元組是深度不可變的類似數組的數據結構。它們不能有未設置的值,只能設置基本類型、其他元組或記錄。元組是基本類型,因此可以按值與其他元組進行深度比較。
  • 記錄是深度不可變的類似對象的數據結構。它們必須使用字符串屬性名,並且只能使用基本類型、其他元組或記錄設置值。記錄可以與其他記錄進行深度比較,並且屬性順序無關緊要。

const 的局限性

經驗豐富的 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>

與標準數組不同,元組必須滿足以下要求:

  1. 它們不能有值為 undefined 的空位。例如,#[1,,,4] 是無效的。
  2. 它們只能設置基本類型、其他元組或記錄。不允許使用數組、對像或函數等類型:
<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>

與標準對像不同,記錄必須滿足以下要求:

  1. 它們必須使用字符串屬性名。例如,#{ Symbol(): 1 } 是無效的。
  2. 它們只能使用基本類型、其他元組或記錄設置值。不允許使用數組、對像或函數等類型:
<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 中的記錄? JavaScript 中的記錄是 ECMAScript 2022 (ES12) 中引入的一種類似對象的結構。它旨在表示具有命名屬性的數據,並且默認情況下是不可變的,因此適合用作數據結構,其中值在創建後不會更改。

記錄與普通的 JavaScript 對像有何不同?與普通的對像不同,JavaScript 中的記錄默認情況下是不可變的,並且一旦設置,其屬性就不能修改。記錄的設計也更可預測,結構更嚴格,因此適合用作數據容器。

什麼是 JavaScript 中的元組? JavaScript 中的元組是一個有序的元素集合,其中每個元素可以是不同類型。元組是不可變的,並且長度固定,提供了一種表示和處理特定順序的固定數量值的方法。

記錄和元組如何增強代碼的可讀性和可維護性?記錄和元組可以通過提供更聲明性和結構化的方式來表示數據來增強代碼的可讀性。不可變性方面也有助於防止意外修改,從而提高代碼的可維護性。

使用記錄和元組時是否存在任何性能方面的考慮?記錄和元組作為不可變數據結構,在某些情況下可以提高性能。但是,必須考慮瀏覽器支持和具體的用例,因為性能影響可能會因 JavaScript 運行時的實現細節而異。

如何在沒有原生支持的環境中為記錄和元組提供 polyfill?截至我的上次更新,可以使用 polyfill 或轉譯器在沒有原生支持的環境中模擬記錄和元組。但是,建議隨時了解 JavaScript 標準和工具的更新,因為生態系統在不斷發展。

以上是記錄和元組:JavaScript的新不成熟的數據類型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn