首頁 >web前端 >js教程 >淺談JavaScript中的Map、WeakMap、Set和WeakSet

淺談JavaScript中的Map、WeakMap、Set和WeakSet

青灯夜游
青灯夜游轉載
2021-01-30 18:19:332376瀏覽

淺談JavaScript中的Map、WeakMap、Set和WeakSet

我猜想,超過70%的JavaScript開發人員只使用物件來收集和維護其專案中的資料。好吧,確實如此,新的集合物件(例如Map和Set)即使在2015年問世也沒有充分利用。

因此,今天,我將討論2015年以來的神奇新功能-MapSetWeakMap#和##WeakSet

在閱讀之前

    這篇文章並不是要告訴你只能用它們。但我見過一些應徵者在編碼考試中使用了其中的一種,我喜歡在某些情況下使用它們。由你決定何時在專案中使用它們。
  • 你應該知道什麼是可迭代的,以便更好地了解我的討論。
Objects

我們應該先討論如何使用物件。

好吧,我相信90%以上的人已經知道這部分內容了,因為你點擊這篇文章是為了了解新的集合對象,但對於JavaScript的初學者來說,我們還是簡單說說它們吧。

const algorithm = { site: "leetcode" };
console.log(algorithm.site); // leetcode

for (const key in algorithm) {
  console.log(key, algorithm[key]);
}

// site leetcode
delete algorithm.site;
console.log(algorithm.site); // undefined

所以我做了一個

algorithm 對象,它的key和value是一個字串類型的值,而我透過用. 關鍵字來呼叫該值。

另外,

for-in 迴圈也很適合在物件中循環。你可以用 [] 關鍵字存取其鍵對應的值。但是不能使用 for-of 循環,因為物件是不可迭代的。

物件的屬性可以用

delete 關鍵字來刪除。這樣就可以徹底擺脫物件的屬性,大家要注意不要跟這種方法混淆。

const algorithm = { site: "leetcode" };
// Property is not removed!!
algorithm.site = undefined;
// Property is removed!!
delete algorithm.site;

algorithm.site = undefined 只是將新值指派給 site

好的,我們已經快速討論了有關物件的一些事項:

    如何新增屬性
  • 如何遍歷物件
  • 如何刪除屬性
Map

Map 是JavaScript中新的集合對象,功能類似於物件。但是,與常規對象相比,存在一些主要差異。

首先,讓我們來看一個建立Map物件的簡單範例。

如何新增屬性

const map = new Map();
// Map(0) {}

Map 不需要建立任何內容,但是新增資料的方式略有不同。

map.set('name', 'john');
// Map(1) {"name" => "john"}

Map 有一個特殊的方法可以在其中新增稱為

set 的屬性。它有兩個參數:鍵是第一個參數,值是第二個參數。

map.set('phone', 'iPhone');
// Map(2) {"name" => "john", "phone" => "iPhone"}
map.set('phone', 'iPhone');
// Map(2) {"name" => "john", "phone" => "iPhone"}

但是,它不允許你在其中新增現有資料。如果 Map 物件中已經存在與新資料的鍵對應的值,則不會新增資料。

map.set('phone', 'Galaxy');
// Map(2) {"name" => "john", "phone" => "Galaxy"}

但是你可以用其他值覆寫現有資料。

如何遍歷物件

Map 是一個可迭代的對象,這表示可以使用

for-of 語句將其對應。

for (const item of map) {
  console.dir(item);
}
// Array(2) ["name", "john"]
// Array(2) ["phone", "Galaxy"]

要記住的一件事是 Map 以數組形式提供數據,你應該解構數組或訪問每個索引以獲取鍵或值。

要只取得鍵或值,還有一些方法可供你使用。

map.keys();
// MapIterator {"name", "phone"}
map.values();
// MapIterator {"john", "Galaxy"}
map.entries();
// MapIterator {"name" => "john", "phone" => "Galaxy"}

你甚至可以使用展開運算元(

...)來取得Map的全部數據,因為展開運算子還可以在幕後與可迭代物件一起運作。

const simpleSpreadedMap = [...map];
// [Array(2), Array(2)]

如何刪除屬性

從 Map 物件中刪除資料也很容易,你所需要做的就是呼叫

delete

map.delete('phone');
// true
map.delete('fake');
// false

delete 傳回布林值,該布林值指示 delete 函數是否成功刪除了資料。如果是,則傳回 true,否則傳回 false

WeakMap

WeakMap起源於Map,因此它們彼此之間非常相似。但是,WeakMap具有很大的不同。

WeakMap的名字是怎麼來的呢?嗯,是因為它與它的引用連結所指向的資料物件的連結或關係沒有Map的連結或關係那麼強,所以它是弱的。

那麼,這到底是什麼意思呢?

差異1:key必須是物件

const John = { name: 'John' };
const weakMap = new WeakMap();
weakMap.set(John, 'student');
// WeakMap {{...} => "student"}
weakMap.set('john', 'student');
// Uncaught TypeError: Invalid value used as weak map key

你可以將任何值作為鍵傳入Map對象,但WeakMap不同,它只接受一個物件作為鍵,否則,它將傳回一個錯誤。

差異2:並非Map中的所有方法都支援

可以使用WeakMap的方法如下。

    delete
  • get
  • has
  • #set
這個主題最大的不同是WeakMap不支援迭代對象的方法。但是為什麼呢?下面將對此進行說明。

區別3:當GC清理引用時,資料會被刪除

與Map相比,這是最大的不同。

let John = { major: "math" };

const map = new Map();
const weakMap = new WeakMap();

map.set(John, 'John');
weakMap.set(John, 'John');

John = null;
/* John 被垃圾收集 */

John 物件被垃圾回收時,Map物件將保持引用鏈接,而WeakMap物件將丟失鏈結。所以當你使用WeakMap時,你應該考慮這個功能。

Set

Set也非常類似Map,但是Set對於單一值更有用。

如何加入屬性

const set = new Set();

set.add(1);
set.add('john');
set.add(BigInt(10));
// Set(4) {1, "john", 10n}

與Map一樣,Set也阻止我們新增相同的值。

set.add(5);
// Set(1) {5}

set.add(5);
// Set(1) {5}

如何遍历对象

由于Set是一个可迭代的对象,因此可以使用 for-offorEach 语句。

for (const val of set) {
  console.dir(val);
}
// 1
// 'John'
// 10n
// 5

set.forEach(val => console.dir(val));
// 1
// 'John'
// 10n
// 5

如何删除属性

这一部分和 Map 的删除完全一样。如果数据被成功删除,它返回 true,否则返回 false

set.delete(5); 
// true

set.delete(function(){});
// false;

如果你不想将相同的值添加到数组表单中,则Set可能会非常有用。

/* With Set */
const set = new Set();
set.add(1);
set.add(2);
set.add(2);
set.add(3);
set.add(3);
// Set {1, 2, 3}

// Converting to Array
const arr = [ ...set ];
// [1, 2, 3]

Object.prototype.toString.call(arr);
// [object Array]

/* Without Set */
const hasSameVal = val => ar.some(v === val);
const ar = [];

if (!hasSameVal(1)) ar.push(1);
if (!hasSameVal(2)) ar.push(2);
if (!hasSameVal(3)) ar.push(3);

WeakSet

与WeakMap一样,WeakSet也将丢失对内部数据的访问链接(如果内部数据已被垃圾收集)。

let John = { major: "math" };

const set = new Set();
const weakSet = new WeakSet();

set.add(John);
// Set {{...}}
weakSet.add(John);
// WeakSet {{...}}

John = null;
/* John 被垃圾收集 */

一旦对象 John 被垃圾回收,WeakSet就无法访问其引用 John 的数据。而且WeakSet不支持 for-offorEach,因为它不可迭代。

比较总结

相同点:添加相同的值不支持。

Map vs. WeakMap:WeakMap仅接受对象作为键,而Map不接受。

Map and Set:

  • 可迭代的对象,支持 for..offorEach... 运算符
  • 脱离GC关系

WeakMap and WeakSet:

  • 不是一个可迭代的对象,不能循环。
  • 如果引用数据被垃圾收集,则无法访问数据。
  • 支持较少的方法。

结语

不过,我想,很多团队或公司还是没有使用Maps或Sets。也许是因为他们觉得没有必要,或者是因为数组仍然可以做到几乎所有他们想要的东西。

然而,在JavaScript中,Maps或Sets可能是非常独特和强大的东西,这取决于每个情况。所以我希望有一天,你能有机会使用它们。

原文地址:https://medium.com/better-programming/map-weakmap-set-weakset-in-javascript-77ecb5161e3

作者:Moon

更多编程相关知识,请访问:编程入门!!

以上是淺談JavaScript中的Map、WeakMap、Set和WeakSet的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除