成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

es6 Map和WeakMap

sPeng / 2701人閱讀

摘要:事實上,不僅僅是數(shù)組,任何具有接口且每個成員都是一個雙元素的數(shù)組的數(shù)據(jù)結(jié)構(gòu)都可以當(dāng)做構(gòu)造函數(shù)的參數(shù)。返回所有成員的遍歷器需要特別注意的是,的遍歷順序就是插入順序。轉(zhuǎn)為轉(zhuǎn)為,正常情況下,所有鍵名都是字符串。

Map

JavaScript 的對象(Object),本質(zhì)上是鍵值對的集合(Hash 結(jié)構(gòu)),但是傳統(tǒng)上只能用字符串當(dāng)作鍵。這給它的使用帶來了很大的限制。
為了解決這個問題,ES6 提供了 Map 數(shù)據(jù)結(jié)構(gòu)。它類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當(dāng)作鍵。也就是說,Object 結(jié)構(gòu)提供了“字符串—值”的對應(yīng),Map 結(jié)構(gòu)提供了“值—值”的對應(yīng),是一種更完善的 Hash 結(jié)構(gòu)實現(xiàn)。如果你需要“鍵值對”的數(shù)據(jù)結(jié)構(gòu),Map 比 Object 更合適。

Map的構(gòu)造
ES6 的 Map 類型是鍵值對的有序列表,而鍵和值都可以是任意類型。 鍵的比較使用的是Object.is() ,因此你能將 5 與 "5"
同時作為鍵,因為它們類型不同。這與使用對象屬性作為鍵的方式(指的是用對象來模擬 Map )截然不同,因為對象的屬性會被強制轉(zhuǎn)換為字符串。
set方法構(gòu)造

你可以調(diào)用 set() 方法并給它傳遞一個鍵與一個關(guān)聯(lián)的值,來給 Map 添加項;此后使用鍵名來調(diào)用 get() 方法便能提取對應(yīng)的值。例如:

let map = new Map();
map.set("title", "Understanding ES6");
map.set("year", 2016);
console.log(map.get("title")); // "Understanding ES6"
console.log(map.get("year")); // 2016
數(shù)組構(gòu)造

依然與 Set 類似,你能將數(shù)組傳遞給 Map 構(gòu)造器,以便使用數(shù)據(jù)來初始化一個 Map 。該數(shù)組中的每一項也必須是數(shù)組,內(nèi)部數(shù)組的首個項會作為鍵,第二項則為對應(yīng)值。因此整個Map 就被這些雙項數(shù)組所填充。例如:

let map = new Map([["name", "Nicholas"], ["age", 25]]);
console.log(map.has("name")); // true
console.log(map.get("name")); // "Nicholas"
console.log(map.size); // 2

通過構(gòu)造器中的初始化, "name" 與 "age" 這兩個鍵就被添加到 map 變量中。雖然由數(shù)組構(gòu)成的數(shù)組看起來有點奇怪,這對于準(zhǔn)確表示鍵來說卻是必要的:因為鍵允許是任意數(shù)據(jù)類型,將鍵存儲在數(shù)組中,是確保它們在被添加到 Map 之前不會被強制轉(zhuǎn)換為其他類型的唯一方法。
Map構(gòu)造函數(shù)接受數(shù)組作為參數(shù),實際上執(zhí)行的是下面的算法。

const items = [
["name", "Nicholas"]
  ["age", 25] ]
  
  const map = new Map();
  
  items.forEach(
    ([key, value]) => map.set(key, value)
  );

事實上,不僅僅是數(shù)組,任何具有 Iterator 接口、且每個成員都是一個雙元素的數(shù)組的數(shù)據(jù)結(jié)構(gòu)都可以當(dāng)做Map構(gòu)造函數(shù)的參數(shù)。這就是說,Set和Map都可以用來生成新的Map

其他構(gòu)造
 const set = new Set([
      ["foo", 1],
      ["bar", 2]
    ]);
const m1 = new Map(set);
m1.get("foo") // 1

const m2 = new Map([["baz", 3]]);
const m3 = new Map(m2);
m3.get("baz") // 3

上面代碼中,我們分別使用 Set 對象和 Map 對象,當(dāng)作Map構(gòu)造函數(shù)的參數(shù),結(jié)果都生成了新的 Map 對象。

Map的屬性和方法 1、屬性

Map 同樣擁有 size 屬性,用于指明包含了多少個鍵值對

2、方法 2.1、操作方法
2.11、set(key, value)

set方法設(shè)置鍵名key對應(yīng)的鍵值為value,然后返回整個 Map 結(jié)構(gòu)。如果key已經(jīng)有值,則鍵值會被更新,否則就新生成該鍵。

const m = new Map();
m.set("edition", 6)        // 鍵是字符串
m.set(262, "standard")     // 鍵是數(shù)值
m.set(undefined, "nah")    // 鍵是 undefined

set方法返回的是當(dāng)前的Map對象,因此可以采用鏈?zhǔn)綄懛ā?/p>

let map = new Map()
  .set(1, "a")
  .set(2, "b")
  .set(3, "c");
2.12、get(key)

get方法讀取key對應(yīng)的鍵值,如果找不到key,返回undefined。

const m = new Map();
const hello = function() {console.log("hello");};
m.set(hello, "Hello ES6!") // 鍵是函數(shù)

m.get(hello)  // Hello ES6!
2.13、has、delete、clear
Map 與 Set 共享了幾個方法,這是有意的,允許你使用相似的方式來與 Map 及 Set 進行交互。以下三個方法在 Map 與 Set
上都存在:
2.13.1、has(key)

has方法返回一個布爾值,表示某個鍵是否在當(dāng)前 Map 對象之中。

const m = new Map();
m.set("edition", 6);
m.set(262, "standard");
m.set(undefined, "nah");
m.has("edition")     // true
m.has("years")       // false
m.has(262)           // true
m.has(undefined)     // true
2.13.2、delete(key)

delete方法刪除某個鍵,返回true。如果刪除失敗,返回false。

const m = new Map();
m.set(undefined, "nah");
m.has(undefined)     // true

m.delete(undefined)
m.has(undefined)       // false
2.13.4、clear()

clear方法清除所有成員,沒有返回值。

let map = new Map();
map.set("foo", true);
map.set("bar", false);

map.size // 2
map.clear()
map.size // 0
2.2、遍歷方法 2.2.1遍歷器生成函數(shù)

? keys():返回鍵名的遍歷器。
? values():返回鍵值的遍歷器。
? entries():返回所有成員的遍歷器

需要特別注意的是,Map 的遍歷順序就是插入順序。

const map = new Map([
  ["F", "no"],
  ["T",  "yes"],
]);

for (let key of map.keys()) {
  console.log(key);
}
// "F"
// "T"

for (let value of map.values()) {
  console.log(value);
}
// "no"
// "yes"

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"

// 或者
for (let [key, value] of map.entries()) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

// 等同于使用map.entries()
for (let [key, value] of map) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

上面代碼最后的那個例子,表示 Map 結(jié)構(gòu)的默認(rèn)遍歷器接口(Symbol.iterator屬性),就是entries方法。

2.2.2、forEach

Map 的 forEach() 方法類似于 Set 與數(shù)組的同名方法,它接受一個能接收三個參數(shù)的回調(diào)函數(shù):

Map 中下個位置的值;

該值所對應(yīng)的鍵;

目標(biāo) Map 自身。

回調(diào)函數(shù)的這些參數(shù)更緊密契合了數(shù)組 forEach() 方法的行為,即:第一個參數(shù)是值、第二個參數(shù)則是鍵(數(shù)組中的鍵是數(shù)值索引)。此處有個示例:

let map = new Map([
  ["name", "Nicholas"], 
  ["age", 25]
]);
map.forEach(function(value, key, ownerMap) {
  console.log(key + " " + value);
  console.log(ownerMap === map);
});

forEach() 的回調(diào)函數(shù)輸出了傳給它的信息。其中 value 與 key 被直接輸出, ownerMap
與 map 進行了比較,說明它們是相等的。這就輸出了:

name Nicholas
true
age 25
true    
Map與其他數(shù)據(jù)結(jié)構(gòu)的相互裝換 Map轉(zhuǎn)數(shù)組:

Map 結(jié)構(gòu)轉(zhuǎn)為數(shù)組結(jié)構(gòu),比較快速的方法是使用擴展運算符(...)。

const map = new Map([
  [1, "one"],
  [2, "two"],
  [3, "three"],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ["one", "two", "three"]
[...map.entries()]
// [[1,"one"], [2, "two"], [3, "three"]]
[...map]
// [[1,"one"], [2, "two"], [3, "three"]]
數(shù)組轉(zhuǎn)為 Map

將數(shù)組傳入 Map 構(gòu)造函數(shù),就可以轉(zhuǎn)為 Map。

new Map([
  [true, 7],
  [{foo: 3}, ["abc"]]
])
// Map {
//   true => 7,
//   Object {foo: 3} => ["abc"]
// }
Map 轉(zhuǎn)為對象

如果所有 Map 的鍵都是字符串,它可以無損地轉(zhuǎn)為對象。

function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}

const myMap = new Map()
  .set("yes", true)
  .set("no", false);
strMapToObj(myMap)
// { yes: true, no: false }

如果有非字符串的鍵名,那么這個鍵名會被轉(zhuǎn)成字符串,再作為對象的鍵名。

對象轉(zhuǎn)為 Map
function objToStrMap(obj) {
  let strMap = new Map();
  for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}

objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}
Map 轉(zhuǎn)為 JSON

Map 轉(zhuǎn)為 JSON 要區(qū)分兩種情況。一種情況是,Map 的鍵名都是字符串,這時可以選擇轉(zhuǎn)為對象 JSON。

function strMapToJson(strMap) {
  return JSON.stringify(strMapToObj(strMap));
}

let myMap = new Map().set("yes", true).set("no", false);
strMapToJson(myMap)
// "{"yes":true,"no":false}"

另一種情況是,Map 的鍵名有非字符串,這時可以選擇轉(zhuǎn)為數(shù)組 JSON。

function mapToArrayJson(map) {
  return JSON.stringify([...map]);
}

let myMap = new Map().set(true, 7).set({foo: 3}, ["abc"]);
mapToArrayJson(myMap)
// "[[true,7],[{"foo":3},["abc"]]]"
JSON 轉(zhuǎn)為 Map

JSON 轉(zhuǎn)為 Map,正常情況下,所有鍵名都是字符串。

function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
}

jsonToStrMap("{"yes": true, "no": false}")
// Map {"yes" => true, "no" => false}

但是,有一種特殊情況,整個 JSON 就是一個數(shù)組,且每個數(shù)組成員本身,又是一個有兩個成員的數(shù)組。這時,它可以一一對應(yīng)地轉(zhuǎn)為 Map。這往往是 Map 轉(zhuǎn)為數(shù)組 JSON 的逆操作。

  function jsonToMap(jsonStr) {
      return new Map(JSON.parse(jsonStr));
    }

jsonToMap("[[true,7],[{"foo":3},["abc"]]]")
// Map {true => 7, Object {foo: 3} => ["abc"]}
WeakMap: WeakMap的特性

WeakMap與Map的區(qū)別有兩點。
首先,WeakMap只接受對象作為鍵名(null除外),不接受其他類型的值作為鍵名。

const map = new WeakMap();
map.set(1, 2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null, 2)
// TypeError: Invalid value used as weak map key

其次,WeakMap的鍵名所指向的對象,不計入垃圾回收機制。
WeakMap的設(shè)計目的在于,有時我們想在某個對象上面存放一些數(shù)據(jù),但是這會形成對于這個對象的引用。請看下面的例子。

const e1 = document.getElementById("foo");
const e2 = document.getElementById("bar");
const arr = [
  [e1, "foo 元素"],
  [e2, "bar 元素"],
];

上面代碼中,e1和e2是兩個對象,我們通過arr數(shù)組對這兩個對象添加一些文字說明。這就形成了arr對e1和e2的引用。
一旦不再需要這兩個對象,我們就必須手動刪除這個引用,否則垃圾回收機制就不會釋放e1和e2占用的內(nèi)存。
// 不需要 e1 和 e2 的時候
// 必須手動刪除引用

arr [0] = null;
arr [1] = null;

上面這樣的寫法顯然很不方便。一旦忘了寫,就會造成內(nèi)存泄露。

WeakMap 就是為了解決這個問題而誕生的,它的鍵名所引用的對象都是弱引用,即垃圾回收機制不將該引用考慮在內(nèi)。因此,只要所引用的對象的其他引用都被清除,垃圾回收機制就會釋放該對象所占用的內(nèi)存。也就是說,一旦不再需要,WeakMap 里面的鍵名對象和所對應(yīng)的鍵值對會自動消失,不用手動刪除引用。

WeakMap的構(gòu)造:

ES6 的 WeakMap 類型是鍵值對的無序列表,其中鍵必須是非空的對象,值則允許是任意類型。 WeakMap 的接口與 Map 的非常相似
// WeakMap 可以使用 set 方法添加成員

const wm1 = new WeakMap();
const key = {foo: 1};
wm1.set(key, 2);
wm1.get(key) // 2

// WeakMap 也可以接受一個數(shù)組,
// 作為構(gòu)造函數(shù)的參數(shù)

const k1 = [1, 2, 3];
const k2 = [4, 5, 6];
const wm2 = new WeakMap([[k1, "foo"], [k2, "bar"]]);
wm2.get(k2) // "bar"
WeakMap的屬性和方法:

WeakMap 與 Map 在 API 上的區(qū)別主要是兩個,一是沒有遍歷操作(即沒有keys()、values()和entries()方法),也沒有size屬性。因為沒有辦法列出所有鍵名,某個鍵名是否存在完全不可預(yù)測,跟垃圾回收機制是否運行相關(guān)。這一刻可以取到鍵名,下一刻垃圾回收機制突然運行了,這個鍵名就沒了,為了防止出現(xiàn)不確定性,就統(tǒng)一規(guī)定不能取到鍵名。二是無法清空,即不支持clear方法。因此,WeakMap只有四個方法可用:get()、set()、has()、delete()。

const wm = new WeakMap();
// size、forEach、clear 方法都不存在
wm.size // undefined
wm.forEach // undefined
wm.clear // undefined
WeakMap常用場景

Weak Map 的最佳用武之地,就是在瀏覽器中創(chuàng)建一個關(guān)聯(lián)到特定 DOM 元素的對象。例如,某些用在網(wǎng)頁上的 JS 庫會維護一個自定義對象,用于引用該庫所使用的每一個 DOM 元素,并且其映射關(guān)系會存儲在內(nèi)部的對象緩存中。
該方法的困難之處在于:如何判斷一個 DOM 元素已不復(fù)存在于網(wǎng)頁中,以便該庫能移除此元素的關(guān)聯(lián)對象。若做不到,該庫就會繼續(xù)保持對 DOM 元素的一個無效引用,并造成內(nèi)存泄漏。使用 Weak Map 來追蹤 DOM 元素,依然允許將自定義對象關(guān)聯(lián)到每個 DOM 元素,而在此對象所關(guān)聯(lián)的 DOM 元素不復(fù)存在時,它就會在 Weak Map 中被自動銷毀。
必須注意的是, Weak Map 的鍵才是弱引用,而值不是。在 Weak Map 的值中存儲對象會阻止垃圾回收,即使該對象的其他引用已全都被移除。

當(dāng)決定是要使用 Weak Map 還是使用正規(guī) Map 時,首要考慮因素在于你是否只想使用對象類型的鍵。如果你打算這么做,那么最好的選擇就是
Weak Map 。因為它能確保額外數(shù)據(jù)在不再可用后被銷毀,從而能優(yōu)化內(nèi)存使用并規(guī)避內(nèi)存泄漏。 要記住 Weak Map
只為它們的內(nèi)容提供了很小的可見度,因此你不能使用 forEach() 方法、size 屬性或 clear()
方法來管理其中的項。如果你確實需要一些檢測功能,那么正規(guī) Map會是更好的選擇,只是一定要確保留意內(nèi)存的使用。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96829.html

相關(guān)文章

  • ES6 系列之 WeakMap

    摘要:一個對象若只被弱引用所引用,則被認(rèn)為是不可訪問或弱可訪問的,并因此可能在任何時刻被回收。也就是說,一旦不再需要,里面的鍵名對象和所對應(yīng)的鍵值對會自動消失,不用手動刪除引用。如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。 前言 我們先從 WeakMap 的特性說起,然后聊聊 WeakMap 的一些應(yīng)用場景。 特性 1. WeakMap 只接受對象作為鍵名 const map = ...

    CollinPeng 評論0 收藏0
  • ES6 - WeakMap

    Set有對應(yīng)的WeakSet, Map也有WeakMap。這一篇,我們就來學(xué)習(xí)一下WeakMap有寫什么特性。先來看一下WeakMap的基本特性: 1: WeakMap是一種存儲多個鍵值對的無序列表 2: WeakMap的鍵必須是非null的對象類型 3: WeakMap的鍵對應(yīng)的值,可以是任意類型 接下來看一下WeakMap的接口方法:一:WeakMap的新建與初始化與Map相同的,WeakM...

    Youngdze 評論0 收藏0
  • 細說es6中的SetMap

    摘要:返回一個布爾值,表示該值是否為的成員。返回鍵名的遍歷器返回鍵值的遍歷器返回鍵值對的遍歷器使用回調(diào)函數(shù)遍歷每個成員需要特別指出的是,的遍歷順序就是插入順序。該數(shù)組的所有成員,都會自動成為實例對象的成員。這意味著,數(shù)組的成員只能是對象。 1.Set ES6 提供了新的數(shù)據(jù)結(jié)構(gòu) Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。Set 本身是一個構(gòu)造函數(shù),用來生成 Set 數(shù)據(jù)結(jié)構(gòu)...

    Ryan_Li 評論0 收藏0
  • 初探ES6中的MapWeakMap

    摘要:對象保存鍵值對。清空用于移除對象中指定的元素。執(zhí)行刪除操作返回一個值,用來表明中是否存在指定元素一樣的后面的會覆蓋前面的值把對象轉(zhuǎn)換為迭代器返回一個新的對象對象是一組鍵值對的集合,其中的鍵是弱引用的。其鍵必須是對象,而值可以是任意的。 Map 對象保存鍵值對。任何值(對象或者原始值) 都可以作為一個鍵或一個值。 使用映射對象 let myMap=new Map(); let keyOb...

    liukai90 評論0 收藏0
  • ES6引入的數(shù)據(jù)結(jié)構(gòu) - ES6 - ECMAScript特性 - Javascript核心

    摘要:引入的數(shù)據(jù)結(jié)構(gòu)新加入的數(shù)據(jù)類型有這些數(shù)據(jù)結(jié)構(gòu)的支持并不廣泛,在寫這篇文章的時候。是或其他可枚舉的對象,其每個元素是的元數(shù)組。開頭的和不對持有引用,不影響。因此,他們沒有辦法對自身的進行直接的枚舉。目前新版的和支持。 原文:http://pij.robinqu.me/JavaScript_Core/ECMAScript/es6/es6_data_types.html 源代...

    fobnn 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<