1. 程式人生 > >ES6 中的 Set、Map 和 WeakMap

ES6 中的 Set、Map 和 WeakMap

提醒:本文最後更新於 1936 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

ES6 新增了幾種集合型別,本文介紹 SetMapWeakMap。比較新的 Firefox、Chrome(需要在 about:flags 啟用實驗性 JavaScript)以及 IE11 都有不同程度的實現。需要注意的是,ES6 規範會一直調整,本文只以當前規範及瀏覽器實現為準。

Set

Set 是 ES6 新增的有序列表集合,它不會包含重複項。之前我們通常用物件(Object)或者陣列(Array)來實現沒有重複項的集合。但物件會對 key 進行 toString() 操作,這會導致某些 key 會意外覆蓋之前的資料;如果 key 本身是一個物件,toString() 也得不到想要的結果,如下:

var o = {};

var key1 = 2;
var key2 = { toString : function() { return 2 } };

var key3 = { x : 1 };
var key4 = { y : 2 };

o[key1] = 1;
o[key2] = 2;
o[key3] = 3;
o[key4] = 4;

// o : Object {2: 2, [object Object]: 4}

陣列可以存放任何型別的資料,不過資料除重需要自己實現。

Set 支援 add(item) 方法,用來向 Set 新增任意型別的元素,如果已經新增過則自動忽略;has(item) 方法用來檢測 Set 中是否存在指定元素;delete(item) 方法用來從 Set 中刪除指定元素;clear() 用來清空 Set;獲取 Set 集合長度用 size 屬性。如下:

var set = new Set();
set.add(window);
set.has(window); // true
set.size; // 1
set.add(window);
set.add(1);
set.size; // 2
set.delete(window);
set.has(window); // false
set.clear();
set.size; // 0

Set 呼叫 add、has、delete 等方法時對 key 進行的比較,不做型別轉換。可以認為使用「===」進行比較,當然也不全是「===」:

  • Set 中,NaN 只能新增一次(雖然NaN === NaN 返回 false);
  • Set 中,「-0」和「0 或 +0」可以同時存在,因為符號不一樣(雖然 -0 === 0 或 -0 === +0 返回 true);

Map

Map 是 ES6 新增的有序鍵值對集合。鍵值對的 key 和 value 都可以是任何型別的元素。通過 set(key, value) 方法為 Map 設定新的鍵值對,如果設定的 key 已經存在則用新的 value 覆蓋,Map 在比較 key 時也不做型別轉換,跟 Set 類似;Map 的 get(key) 方法用來獲取指定 key 的值;Map 的 has(key) 、 delete(key) 、clear() 這些方法和 size 屬性,與 Set 類似,直接看程式碼:

var map = new Map();
var key1 = {toString : function() { return 2}};
var key2 = 2;
map.set(key1, 1);
map.set(key2, 2);

map.has(key1); // true
map.has('2'); // false,型別不同
map.delete(2);
map.size; // 1
map.get(key2); // undefined

迭代

我們沒辦法像陣列一樣用 for 迴圈來迭代 Set,也沒辦法像物件一樣用 for...in 來迭代 Map。但是可以用 ES6 提供的新方法 for...of 來遍歷它們。

Set 和 Map 有幾個方法會返回可迭代物件(Iterator Objects),分別是 entries()、keys() 和 values()。直接遍歷 Set/Map,等同於遍歷 entries();keys() 和 values() 則分別返回 key 和 value 的集合;對於 Set,key 和 value 是一樣的。這些方法和 for...of 現階段都只有 Firefox 支援,下面的例子需要在 Firefox 下執行:

var set = new Set();
set.add('this is a demo.');
set.add(window);
set.add(top);

for(let item of set) {
    console.log(item);
}

WeakMap

WeakMap 相對於普通的 Map,也是鍵值對集合,只不過 WeakMap 的 key 只能是非空物件(non-null object)。WeakMap 對它的 key 僅保持弱引用,也就是說它不阻止垃圾回收器回收它所引用的 key。WeakMap 最大的好處是可以避免記憶體洩漏。一個僅被 WeakMap 作為 key 而引用的物件,會被垃圾回收器回收掉。

WeakMap 擁有和 Map 類似的 set(key, value) 、get(key)、has(key)、delete(key) 和 clear() 方法,但沒有 size 屬性,也沒有任何與迭代有關的方法。

為了演示 WeakMap 與記憶體回收的關係,我用 IE11 做了一個簡單的測試。IE11 的 F12 開發者工具改進很大,下次找機會單獨介紹。測試流程如下:

  1. 建立一個全域性的 Map/WeakMap 物件;
  2. 進入區域性作用域,建立大量物件作為 key,加到 Map/WeakMap 中;
  3. 離開區域性作用域,檢查第 2 步建立的大量物件是否被回收;
  4. 手動回收 Map/WeakMap 物件;

記憶體使用結果如下:

map & weakmap

紅線位置即為測試的第 2 步,可以看到給 Map/WeakMap 新增大量物件後,記憶體使用大幅增加;但 WeakMap 沒有阻止這些物件隨後被回收,記憶體使用馬上跌落,與 Map 對比非常明顯;最後手動回收 Map/WeakMap 之後,全部記憶體都會被回收。

WeakSet?

ES6 還定義了另外一種集合型別:WeakSet,但目前還沒有瀏覽器實現。顧名思義,它應該是沒有 size 屬性、不能迭代的 Set;且只能新增非空物件。這裡有 V8 引擎實現 WeakSet 的程式碼,大家可以先看看。

--EOF--

提醒:本文最後更新於 1936 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

相關推薦

ES6 SetMap WeakMap

提醒:本文最後更新於 1936 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 ES6 新增了幾種集合型別,本文介紹 Set、Map 和 WeakMap。比較新的 Firefox、Chrome(需要在 about:flags 啟用實驗性 JavaScript)以及 IE11 都有不同程度的實

KotlinSetMapList 容器使用

前言 之前講了Kotlin中基本資料型別和String字串拼接的一些基本用法,這裡學習一下kotlin中陣列和集合容器,其實挺想上來就用kotlin寫頁面的,畢竟那樣有成就感,也不會枯燥無味,但是從java學過來深知基礎的重要,所以還是一步一步來。 陣列宣告 k

Java集合類setListmap的遍歷方式

Java中集合類的遍歷方式 Java中集合分為set、List和map。 1.set集合 set集合常用的有兩種遍歷方式: Set<String>  set = new HashSet<String>(); 第一種利用for迴圈: for(S

ES6新特性:JavascriptMapWeakMap物件

  Map物件   Map物件是一種有對應 鍵/值 對的物件, JS的Object也是 鍵/值 對的物件 ;   ES6中Map相對於Object物件有幾個區別:   1:Object物件有原型, 也就是說他有預設的key值在物件上面, 除非我們使用Object.create(null)建立一個沒有原型

Java集合:ListSetmap的區別具體的使用場景高頻問題解析

1. Interface Iterable 迭代器介面,這是Collection類的父介面。實現這個Iterable介面的物件允許使用foreach進行遍歷,也就是說,所有的Collection集合物件都具有"foreach可遍歷性"。這個Iterable介面只有一個方法: iterator()。它返回一個代

JavaarraySetListMap的比較總結

array、List、Set、Map的區別: 1、array:陣列,可以儲存物件和基本資料型別,長度固定。 2、Collection介面:集合(單列),用於儲存物件、不能儲存基本資料型別(int,char等),但可以儲存基本資料型別包裝類(int-Integer,char-

Java把物件物件beanlist集合物件陣列MapSet以及字串轉換成Json

把Java對常用的一些資料轉換成Json,以便前臺的呼叫. 物件轉換為Json public class ConvertJson { /** * 物件轉換為Json * @param obj * @

javaListSetMap集合遍歷的幾種方式小結比較

一、集合類的通用遍歷方式, 用迭代器迭代:1.迭代遍歷whileIterator it = list.iterator();while(it.hasNext()){Object obj = it.next();System.out.println(it.next());}2.

listsetmap的差別叠代器讀取數據

lin style tor shm obj span col ring value package collectiondemo; import java.util.ArrayList; import java.util.LinkedList; import java.

Js基礎知識7-Es6新增對象Mapset數據結構

。。 log trie tty get 代碼 構造 ivr 錯誤 前言 JavaScript中對象的本質是鍵值對的集合,ES5中的數據結構,主要是用Array和Object,但是鍵只能是字符串。為了彌補這種缺憾,ES6帶來了一種新的數據結構Map。 Map也是鍵值對的集

ES6 MapWeakMap

1.Map的學習 a.Map的定義:“值-值”,更完善的Hash結構; const m = new Map() const o = { p: 'hello Map' } m.set(o, 'content') const m = new Map(o) b.Map的例項屬性與操作方法 map.si

Java基礎知識回顧之四 ----- 集合ListMapSet

linked 訪問速度 因此 比較 foreach循環 代碼示例 的區別 不同的 寫法 前言 在上一篇中回顧了Java的三大特性:封裝、繼承和多態。本篇則來介紹下集合。 集合介紹 我們在進行Java程序開發的時候,除了最常用的基礎數據類型和String對象外,也經常會用到集

ES6新增的資料結構MapWeakMap

一、Map Map物件是一種有對應 鍵/值 對的物件, JS的Object也是 鍵/值 對的物件 ; ES6中Map相對於Object物件有幾個區別: 1、Object物件有原型, 也就是說他有預設的key值在物件上面, 除非我們使用Object.create(obj)建立一個沒

SetWeakSetMap以及WeakMap結構基本知識點

### set 1、set類似於陣列,但是成員都是唯一的,沒有重複的值; 2、Set本身是一個建構函式,用來生成Set資料結構 ``` const s = new Set(); let arr =[2,3,4,2,3,4,3]; arr.forEach(x => s.add(x

Js/jQuery ArraySetMapObjectJdom 的 forfor ineachforEach 比較

for for in each forEach Array √ √ √ √ Set × × × √ Map × × × √ Object × √

SetListMap的區別

Set、List和Map是java容器框架的三個最重要的介面。 List提供了一個有序且有索引的容器,它允許重複值的出現。 Set提供了一個無序的唯一物件的容器,也就是說Set不允許重複值。 Map提供了一個基於鍵值對以及雜湊的資料結構。 容器API裡都

ES6語法筆記(SymbolSetMapProxyReflectPromise)

item 鍵值 getdate 循環 清除 blue sin led 返回對象 **以下內容均摘自ECMAScript 6 入門——阮一峰 一、Symbol數據類型(undefined、null、布爾值(Boolean)、字符串(String)、數值(Number)、對象(

ListSetMap 底層實現使用推薦

List、Set、Map 底層實現和使用推薦 List和Set和Map的實現方式以及儲存方式? List 常用實現方式有:ArrayList和LinkedList ArrayList 的儲存方式:陣列,查詢快 LinkedList的儲存方式:連結串列,插入,刪除快 Set 常用實

javaListSetMap之間的關係

java中關於實現陣列有許多種方法,諸如ArrayList,Hashmap,Linklist....此類太多的陣列型別實在是讓人暈頭轉向,很難掌握其要點.今天我就帶大家來整理一下List,set,map之間的區別和聯絡: 首先說明一下他們之間所有的所屬關係: 1.Collection介

ES6JsonStringMapObject之間的轉換

'use strict'; import React, {Component} from 'react' /** *JsonUitl的實現 */ class JsonUtils extends React.Component { /** *字串轉json * */ static stringToJs