本文探討了四個新的ES6集合以及它們帶來的好處。
大多數主要的編程語言都有幾種類型的數據集合。 Python有列表、元組和字典。 Java有列表、集合、映射、隊列。 Ruby有哈希和數組。到目前為止,JavaScript只有數組。對象和數組是JavaScript的得力助手。 ES6引入了四個新的數據結構,它們將增強語言的強大功能和表達能力:Map、Set、WeakSet和WeakMap。
HashMap、字典和哈希是各種編程語言存儲鍵值對的幾種方法,這些數據結構針對快速檢索進行了優化。
在ES5中,JavaScript對象(只是具有鍵和值的屬性的任意集合)可以模擬哈希,但是使用對像作為哈希有幾個缺點。
JavaScript對象屬性鍵必須是字符串,這限制了它們作為不同數據類型鍵值對集合的能力。當然,您可以將其他數據類型強制轉換為字符串,但這會增加額外的工作。
對象並非設計為集合,因此沒有有效的方法來確定對像有多少屬性。 (例如,Object.keys速度很慢)。當您循環遍歷對象的屬性時,您還會獲得其原型屬性。您可以向所有對象添加可迭代屬性,但並非所有對像都旨在用作集合。您可以使用for … in循環和hasOwnProperty()方法,但這只是一個變通方法。當您循環遍歷對象的屬性時,屬性不一定會按照插入的順序檢索。
對象具有內置方法,如constructor、toString和valueOf。如果將其中一個添加為屬性,則可能導致衝突。您可以使用Object.create(null)創建一個裸對象(不繼承自object.prototype),但這仍然只是一個變通方法。
ES6包含新的集合數據類型,因此不再需要使用對象並忍受它們的缺點。
Map是我們將要檢查的第一個數據結構/集合。 Map是任何類型的鍵值對的集合。創建新的Map、添加/刪除值、循環遍歷鍵/值以及有效地確定其大小很容易。以下是關鍵方法:
<code class="language-javascript">const map = new Map(); // 创建一个新的Map map.set('hobby', 'cycling'); // 设置键值对 const foods = { dinner: 'Curry', lunch: 'Sandwich', breakfast: 'Eggs' }; // 新对象 const normalfoods = {}; // 新对象 map.set(normalfoods, foods); // 设置两个对象作为键值对 for (const [key, value] of map) { console.log(`${key} = ${value}`); // hobby = cycling [object Object] = [object Object] } map.forEach((value, key) => { console.log(`${key} = ${value}`); }, map); // hobby = cycling [object Object] = [object Object] map.clear(); // 清除键值对 console.log(map.size === 0); // True </code>
在JSBin上運行此示例
Set是有序的值列表,不包含重複項。 Set不是像數組那樣被索引,而是使用鍵訪問。 Set已經存在於Java、Ruby、Python和許多其他語言中。 ES6 Set與其他語言中的Set之間的一個區別是,順序在ES6中很重要(在許多其他語言中並非如此)。以下是關鍵的Set方法:
<code class="language-javascript">const planetsOrderFromSun = new Set(); planetsOrderFromSun.add('Mercury'); planetsOrderFromSun.add('Venus').add('Earth').add('Mars'); // 可链式方法 console.log(planetsOrderFromSun.has('Earth')); // True planetsOrderFromSun.delete('Mars'); console.log(planetsOrderFromSun.has('Mars')); // False for (const x of planetsOrderFromSun) { console.log(x); // 输入和输出顺序相同 - Mercury Venus Earth } console.log(planetsOrderFromSun.size); // 3 planetsOrderFromSun.add('Venus'); // 尝试添加重复项 console.log(planetsOrderFromSun.size); // 仍然是3,没有添加重复项 planetsOrderFromSun.clear(); console.log(planetsOrderFromSun.size); // 0 </code>
在JSBin上運行此示例
JavaScript垃圾回收是一種內存管理形式,其中不再引用的對象會自動刪除,並且其資源會被回收。
Map和Set對對象的引用是強持有的,並且不允許垃圾回收。如果map/set引用不再需要的大的對象(例如已經從DOM中刪除的DOM元素),這可能會變得很昂貴。
為了解決這個問題,ES6還引入了兩個新的弱集合,稱為WeakMap和WeakSet。這些ES6集合是“弱”的,因為它們允許不再需要的對像從內存中清除。
WeakMap是我們介紹的第三個新的ES6集合。 WeakMap類似於普通的Map,但方法較少,並且在垃圾回收方面存在上述差異。
<code class="language-javascript">const aboutAuthor = new WeakMap(); // 创建新的WeakMap const currentAge = {}; // 键必须是对象 const currentCity = {}; // 键必须是对象 aboutAuthor.set(currentAge, 30); // 设置键值 aboutAuthor.set(currentCity, 'Denver'); // 键值可以是不同数据类型 console.log(aboutAuthor.has(currentCity)); // 测试WeakMap是否包含键 aboutAuthor.delete(currentAge); // 删除键 </code>
WeakMap有幾個流行的用例。它們可以用來保持對象的私有數據私有,也可以用來跟踪DOM節點/對象。
以下示例來自JavaScript專家Nicholas C. Zakas:
<code class="language-javascript">var Person = (function() { var privateData = new WeakMap(); function Person(name) { privateData.set(this, { name: name }); } Person.prototype.getName = function() { return privateData.get(this).name; }; return Person; }()); </code>
在這裡使用WeakMap簡化了保持對像數據私有的過程。可以引用Person對象,但是如果沒有特定的Person實例,則不允許訪問privateDataWeakMap。
Google Polymer項目在一個名為PositionWalker的代碼片段中使用WeakMap。
PositionWalker跟踪DOM子樹中的位置,作為當前節點和該節點內的偏移量。
WeakMap用於跟踪DOM節點的編輯、刪除和更改:
<code class="language-javascript">const map = new Map(); // 创建一个新的Map map.set('hobby', 'cycling'); // 设置键值对 const foods = { dinner: 'Curry', lunch: 'Sandwich', breakfast: 'Eggs' }; // 新对象 const normalfoods = {}; // 新对象 map.set(normalfoods, foods); // 设置两个对象作为键值对 for (const [key, value] of map) { console.log(`${key} = ${value}`); // hobby = cycling [object Object] = [object Object] } map.forEach((value, key) => { console.log(`${key} = ${value}`); }, map); // hobby = cycling [object Object] = [object Object] map.clear(); // 清除键值对 console.log(map.size === 0); // True </code>
WeakSet是其元素在不再需要它們引用的對象時可以進行垃圾回收的Set集合。 WeakSet不允許迭代。它們的用例相當有限(至少目前是這樣)。大多數早期採用者說WeakSet可以用來標記對象而無需修改它們。 ES6-Features.org有一個從WeakSet添加和刪除元素的示例,以便跟踪對像是否已被標記:
<code class="language-javascript">const planetsOrderFromSun = new Set(); planetsOrderFromSun.add('Mercury'); planetsOrderFromSun.add('Venus').add('Earth').add('Mars'); // 可链式方法 console.log(planetsOrderFromSun.has('Earth')); // True planetsOrderFromSun.delete('Mars'); console.log(planetsOrderFromSun.has('Mars')); // False for (const x of planetsOrderFromSun) { console.log(x); // 输入和输出顺序相同 - Mercury Venus Earth } console.log(planetsOrderFromSun.size); // 3 planetsOrderFromSun.add('Venus'); // 尝试添加重复项 console.log(planetsOrderFromSun.size); // 仍然是3,没有添加重复项 planetsOrderFromSun.clear(); console.log(planetsOrderFromSun.size); // 0 </code>
Map和Set是鍵值對的漂亮的新ES6集合。也就是說,JavaScript對象仍然可以在許多情況下用作集合。除非情況需要,否則無需切換到新的ES6集合。
MDN有一個很好的問題列表,用於確定何時使用對像或鍵控集合:
JavaScript集合以前非常有限,但這已通過ES6得到糾正。這些新的ES6集合將增強語言的強大功能和靈活性,並簡化採用它們的JavaScript開發人員的任務。
本文是來自Microsoft技術佈道者和DevelopIntelligence關於實用JavaScript學習、開源項目和互操作性最佳實踐(包括Microsoft Edge瀏覽器和新的EdgeHTML渲染引擎)的Web開發系列的一部分。 DevelopIntelligence通過appendTo(其專注於前端的博客和課程網站)提供JavaScript培訓和React培訓課程。
我們鼓勵您在包括Microsoft Edge(Windows 10的默認瀏覽器)在內的各種瀏覽器和設備上進行測試,可以使用dev.microsoftedge.com上的免費工具,包括EdgeHTML問題跟踪器,您可以在其中報告或搜索EdgeHTML問題,例如網站渲染或標準合規性問題。此外,請訪問Edge博客,以獲取來自Microsoft開發人員和專家的最新信息。
在JavaScript ES6中,Map和WeakMap都用於存儲鍵值對。但是,它們之間存在一些顯著差異。首先,在Map中,鍵可以是任何類型,而在WeakMap中,鍵必須是對象。其次,Map具有size屬性,允許您檢查鍵值對的數量,但WeakMap沒有此屬性。最後,Map對鍵對象持有強引用,這意味著只要Map存在,它們就沒有資格進行垃圾回收。另一方面,WeakMap對鍵對象持有弱引用,這意味著如果對對像沒有其他引用,則可以對其進行垃圾回收。
與Map和Set不同,WeakMap和WeakSet沒有迭代其元素的方法。這是因為它們旨在對它們的鍵(WeakMap)或值(WeakSet)持有弱引用,這意味著這些可以在任何時間進行垃圾回收。因此,無法保證在嘗試迭代元素時元素仍然存在。如果您需要迭代集合,則應改用Map或Set。
不可以,您不能在WeakMap或WeakSet中使用原始數據類型作為鍵。這些集合中的鍵必須是對象。這是因為WeakMap和WeakSet對它們的鍵持有弱引用,這意味著如果對它們沒有其他引用,則可以對鍵進行垃圾回收。原始數據類型(例如數字和字符串)不會像對像那樣進行垃圾回收,因此它們不能用作這些集合中的鍵。
WeakMap和WeakSet具有一些獨特的特性,在某些情況下,它們可能比Map或Set更合適。因為它們對它們的鍵(WeakMap)或值(WeakSet)持有弱引用,所以當它們不再使用時,可以對其進行垃圾回收。如果您想將其他數據與對象關聯,但又不想阻止對像在不再需要時進行垃圾回收,這將非常有用。此外,因為WeakMap和WeakSet沒有迭代其元素的方法,所以它們可以為它們存儲的數據提供一定程度的隱私。
當WeakMap或WeakSet中的鍵被垃圾回收時,集合中的相應條目會自動刪除。這是因為這些集合對它們的鍵持有弱引用,這意味著當它們不再使用時,可以對鍵進行垃圾回收。此功能對於管理JavaScript應用程序中的內存非常有用,因為它確保與不再使用的對象關聯的數據也會被清除。
是的,WeakMap和WeakSet非常適合存儲臨時數據。因為它們對它們的鍵(WeakMap)或值(WeakSet)持有弱引用,所以當它們不再使用時,可以對其進行垃圾回收。這意味著當鍵被垃圾回收時,存儲在這些集合中的數據也會被清除。這對於存儲僅在短時間內需要的有用,因為您不必擔心手動清理它。
您可以使用has方法來檢查WeakMap或WeakSet是否包含某個鍵。此方法返回一個布爾值,指示該鍵是否存在於集合中。但是,請記住,您不能使用此方法來檢查WeakSet中的某個值,因為此集合中的值是不可訪問的。
是的,您可以使用delete方法從WeakMap中刪除條目。此方法刪除與給定鍵關聯的條目,並返回一個布爾值,指示該鍵是否存在於集合中。但是,您不能從WeakSet中刪除條目,因為此集合沒有delete方法。
不可以,您不能清除WeakMap或WeakSet中的所有條目。這些集合沒有clear方法,該方法在Map和Set中可用。這是因為WeakMap和WeakSet旨在在鍵被垃圾回收時自動清理它們的條目。
不可以,您無法獲取WeakMap或WeakSet的大小。這些集合沒有size屬性,該屬性在Map和Set中可用。這是因為由於垃圾回收,WeakMap或WeakSet的大小可以隨時更改。
以上是ES6集合:使用地圖,設置,弱圖,弱點的詳細內容。更多資訊請關注PHP中文網其他相關文章!