摘要:數(shù)據(jù)類型基本用法提供了一種類似于數(shù)組的新的數(shù)據(jù)結(jié)構(gòu)。實例屬性和方法本身是一個構(gòu)造函數(shù),用來生成數(shù)據(jù)結(jié)構(gòu)。返回一個布爾值,表示該值是否為的成員。任何具有接口且每個成員都是一個雙元素的數(shù)組的數(shù)據(jù)結(jié)構(gòu)都可以當(dāng)作構(gòu)造函數(shù)的參數(shù)。
Set數(shù)據(jù)類型
基本用法
ES6 提供了一種類似于數(shù)組的新的數(shù)據(jù)結(jié)構(gòu) Set。它的成員的值都是唯一的,沒有重復(fù)的值。
const s = new Set(); [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)); for (let i of s) { console.log(i); } // 2 3 5 4 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]); items.size // 5 Array.from方法可以將 Set 結(jié)構(gòu)轉(zhuǎn)為數(shù)組。 Array.from(items) //[1, 2, 3, 4, 5]
有沒有很開心?想想之前數(shù)組去重要雙重循環(huán)、indexOf各種判斷!用這個進行數(shù)組去重是不是很爽?
但是要注意:
向 Set 加入值的時候,不會發(fā)生類型轉(zhuǎn)換,所以5和"5"是兩個不同的值。Set 內(nèi)部判斷兩個值是否不同,使用的算法叫做“Same-value-zero equality”,它類似于精確相等運算符(===),主要的區(qū)別是向 Set 加入值時認(rèn)為NaN等于自身,而精確相等運算符認(rèn)為NaN不等于自身。
實例屬性和方法
Set本身是一個構(gòu)造函數(shù),用來生成 Set 數(shù)據(jù)結(jié)構(gòu)。
實例屬性
Set.prototype.constructor:構(gòu)造函數(shù),默認(rèn)就是Set函數(shù)。
Set.prototype.size:返回Set實例的成員總數(shù)。
實例方法
Set 實例的方法分為兩大類:操作方法(用于操作數(shù)據(jù))和遍歷方法(用于遍歷成員)
1、操作方法
Set.prototype.add(value):添加某個值,返回 Set 結(jié)構(gòu)本身。
Set.prototype.delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
Set.prototype.has(value):返回一個布爾值,表示該值是否為Set的成員。
Set.prototype.clear():清除所有成員,沒有返回值。
2、遍歷方法
Set.prototype.keys():返回鍵名的遍歷器
Set.prototype.values():返回鍵值的遍歷器
Set.prototype.entries():返回鍵值對的遍歷器
Set.prototype.forEach():使用回調(diào)函數(shù)遍歷每個成員,沒有返回值。
由于 Set 結(jié)構(gòu)沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),所以keys方法和values方法的行為完全一致。
WeakSet數(shù)據(jù)類型WeakSet與Set數(shù)據(jù)結(jié)構(gòu)類似,但是有2個不同點。
1、WeakSet 的成員只能是對象,而不能是其他類型的值
2、WeakSet 中的對象都是弱引用。如果其他對象都不再引用該對象,那么垃圾回收機制會自動回收該對象所占用的內(nèi)存,不考慮該對象還存在于 WeakSet 之中。
由于上面這個特點,WeakSet 的成員是不適合引用的,因為它會隨時消失。另外,由于 WeakSet 內(nèi)部有多少個成員,取決于垃圾回收機制有沒有運行,運行前后很可能成員個數(shù)是不一樣的,而垃圾回收機制何時運行是不可預(yù)測的,因此 ES6 規(guī)定 WeakSet 不可遍歷。也就沒有size屬性。
WeakSet 結(jié)構(gòu)有三個方法。
WeakSet.prototype.add(value):向 WeakSet 實例添加一個新成員。
WeakSet.prototype.delete(value):清除 WeakSet 實例的指定成員。
WeakSet.prototype.has(value):返回一個布爾值,表示某個值是否在 WeakSet 實例之中。
const foos = new WeakSet() class Foo { constructor() { foos.add(this) } method () { if (!foos.has(this)) { throw new TypeError("Foo.prototype.method 只能在Foo的實例上調(diào)用!"); } } }
上面代碼保證了Foo的實例方法,只能在Foo的實例上調(diào)用。這里使用 WeakSet 的好處是,foos對實例的引用,不會被計入內(nèi)存回收機制,所以刪除實例的時候,不用考慮foos,也不會出現(xiàn)內(nèi)存泄漏。
Map數(shù)據(jù)類型基本用法
由于ES5的Object提供的hash(鍵值對)里只能用字符串當(dāng)作鍵,會有很大的限制。所以ES6提供了更接近hash結(jié)構(gòu)Map。
//old const data = {}; const element = document.getElementById("myDiv"); data[element] = "metadata"; data["[object HTMLDivElement]"] // "metadata" //new const m = new Map(); const o = {p: "Hello World"}; m.set(o, "content") m.get(o) // "content" m.has(o) // true m.delete(o) // true m.has(o) // false
任何具有 Iterator 接口、且每個成員都是一個雙元素的數(shù)組的數(shù)據(jù)結(jié)構(gòu)都可以當(dāng)作Map構(gòu)造函數(shù)的參數(shù)。這就是說,Set和Map都可以用來生成新的 Map。
//數(shù)組 const map = new Map([ ["name", "張三"], ["title", "Author"] ]); console.log(map.size) // 2 console.log(map.has("name")) // true console.log(map.get("name")) // "張三" console.log(map.has("title")) // true console.log(map.get("title")) // "Author" //Set const set = new Set([ ["foo", 1], ["bar", 2] ]); const m1 = new Map(set); m1.get("foo") // 1 //Map const m2 = new Map([["baz", 3]]); const m3 = new Map(m2); m3.get("baz") // 3
注意,
1、讀取一個未知的鍵,返回undefined。
2、只有對同一個對象的引用,Map 結(jié)構(gòu)才將其視為同一個鍵。
3、Map 的鍵如果是一個簡單類型的值(數(shù)字、字符串、布爾值),則只要兩個值嚴(yán)格相等,Map 將其視為一個鍵,比如0和-0就是一個鍵,布爾值true和字符串true則是兩個不同的鍵。另外,undefined和null也是兩個不同的鍵。雖然NaN不嚴(yán)格相等于自身,但 Map 將其視為同一個鍵。
new Map().get("asfddfsasadf") // undefined const map = new Map(); map.set(["a"], 555); map.get(["a"]) // undefined
實例的屬性和方法
實例屬性
size屬性返回 Map 結(jié)構(gòu)的成員總數(shù)。
const map = new Map(); map.set("foo", true); map.set("foo", false); map.size // 1
方法
1、操作方法
Map.prototype.set(key, value);設(shè)置鍵名key對應(yīng)的鍵值為value;會覆蓋原值
Map.prototype.get(key);讀取key對應(yīng)的鍵值,找不到會返回undefined。
Map.prototype.has(key);表示某個鍵是否在當(dāng)前 Map 對象之中,has方法返回一個布爾值
Map.prototype.delete(key);delete方法刪除某個鍵,返回true。如果刪除失敗,返回false。
Map.prototype.clear();clear方法清除所有成員,沒有返回值。
2、遍歷方法
Map.prototype.keys():返回鍵名的遍歷器。
Map.prototype.values():返回鍵值的遍歷器。
Map.prototype.entries():返回所有成員的遍歷器。
Map.prototype.forEach():遍歷 Map 的所有成員。
Map 的遍歷順序就是插入順序
與其他數(shù)據(jù)結(jié)構(gòu)的互相轉(zhuǎn)換
(1)Map 轉(zhuǎn)為數(shù)組
Map 轉(zhuǎn)為數(shù)組最方便的方法,就是使用擴展運算符(...)。
const myMap = new Map() .set(true, 7) .set({foo: 3}, ["abc"]); [...myMap] // [ [ true, 7 ], [ { foo: 3 }, [ "abc" ] ] ]
(2)數(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"] // }
(3)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)成字符串,再作為對象的鍵名。
(4)對象轉(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}
(5)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"]]]"
(6)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數(shù)據(jù)結(jié)構(gòu)
基本用法
WeakMap結(jié)構(gòu)與Map結(jié)構(gòu)類似,但是有兩點區(qū)別:
1、WeakMap只接受對象作為鍵名(null除外),不接受其他類型的值作為鍵名。
2、WeakMap的鍵名所指向的對象,不計入垃圾回收機制。同WeakSet
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也不能遍歷,所以size、forEach、clear 方法都不存在;而且也不能清空,所以不支持clear方法;。因此,WeakMap只有四個方法可用:get()、set()、has()、delete()。
WeakMap 的用途
WeakMap 應(yīng)用的典型場合就是 DOM 節(jié)點作為鍵名。下面是一個例子。
let myElement = document.getElementById("logo"); let myWeakmap = new WeakMap(); myWeakmap.set(myElement, {timesClicked: 0}); myElement.addEventListener("click", function() { let logoData = myWeakmap.get(myElement); logoData.timesClicked++; }, false);
上面代碼中,myElement是一個 DOM 節(jié)點,每當(dāng)發(fā)生click事件,就更新一下狀態(tài)。我們將這個狀態(tài)作為鍵值放在 WeakMap 里,對應(yīng)的鍵名就是myElement。一旦這個 DOM 節(jié)點刪除,該狀態(tài)就會自動消失,不存在內(nèi)存泄漏風(fēng)險。
WeakMap 的另一個用處是部署私有屬性。
const _counter = new WeakMap(); const _action = new WeakMap(); class Countdown { constructor(counter, action) { _counter.set(this, counter); _action.set(this, action); } dec() { let counter = _counter.get(this); if (counter < 1) return; counter--; _counter.set(this, counter); if (counter === 0) { _action.get(this)(); } } } const c = new Countdown(2, () => console.log("DONE")); c.dec() c.dec() // DONE
上面代碼中,Countdown類的兩個內(nèi)部屬性_counter和_action,是實例的弱引用,所以如果刪除實例,它們也就隨之消失,不會造成內(nèi)存泄漏。
參考文章
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105594.html
摘要:但是有了尾調(diào)用優(yōu)化之后,遞歸函數(shù)的性能有了提升。常被用來檢查對象中是否存在某個鍵名,集合常被用來獲取已存的信息。循環(huán)解構(gòu)對象本身不支持迭代,但是我們可以自己添加一個生成器,返回一個,的迭代器,然后使用循環(huán)解構(gòu)和。 一、let和const 在JavaScript中咱們以前主要用關(guān)鍵var來定義變量,ES6之后,新增了定義變量的兩個關(guān)鍵字,分別是let和const。對于變量來說,在ES5中...
摘要:經(jīng)常會用到的的知識點提到我們就來說說,也是誕生,它的初始名叫。又名,在,和大受重用。年,負(fù)責(zé)制定規(guī)范草案的委員會決定將定義新標(biāo)準(zhǔn)的制度改為一年一次出現(xiàn)。它們在規(guī)范的先前版本中被稱為模板字符串。它與數(shù)組非常相似,但是數(shù)據(jù)結(jié)構(gòu)的成員都是唯一的。 經(jīng)常會用到的es6的知識點 提到es6我們就來說說javascript,es6也是ES2015 1995:JavaScript誕生,它的初始名叫...
摘要:執(zhí)行函數(shù)會返回一個遍歷器對象,每一次函數(shù)里面的都相當(dāng)一次遍歷器對象的方法,并且可以通過方法傳入自定義的來改變函數(shù)的行為。函數(shù)可以通過配合函數(shù)更輕松更優(yōu)雅的實現(xiàn)異步編程和控制流管理。它和構(gòu)造函數(shù)的不同點類的內(nèi)部定義的所有方法,都是不可枚舉的。 let const的命令 在ES6之前,聲明變量只能用var,var方式聲明變量其實是很不合理的,準(zhǔn)確的說,是因為ES5里面沒有塊級作用域是很不合...
摘要:前言新增了兩種基本的原生數(shù)據(jù)集合和加上和現(xiàn)在共有四種,以及由兩者衍生出的弱引用集合和。其本身是生成實例數(shù)據(jù)集合的構(gòu)造函數(shù),可以接受一個數(shù)組或具有接口的數(shù)據(jù)結(jié)構(gòu)作為參數(shù)用來初始化。返回鍵值對的遍歷器對象,鍵值對為鍵名鍵值。 前言 ES6新增了兩種基本的原生數(shù)據(jù)集合:Set和Map(加上Array和Object現(xiàn)在共有四種),以及由兩者衍生出的弱引用集合:WeakSet和WeakMap。從...
摘要:新增了數(shù)據(jù)結(jié)構(gòu),對象保存鍵值對,任何值原始值或?qū)ο蠖伎梢宰鳛橐粋€鍵或一個值?;居梅▽嵗膶傩院筒僮鞣椒ǚ椒ㄔO(shè)置鍵名對應(yīng)的鍵值為,然后返回整個結(jié)構(gòu)。獲取的值方法返回一個布爾值,表示某個鍵是否在當(dāng)前對象之中。如果刪除失敗,返回。 ES6新增了 Map數(shù)據(jù)結(jié)構(gòu),Map對象保存鍵值對,任何值(原始值或?qū)ο螅┒伎梢宰鳛橐粋€鍵或一個值。 基本用法 let map = new Map(); let...
閱讀 786·2023-04-25 17:33
閱讀 3641·2021-07-29 14:49
閱讀 2488·2019-08-30 15:53
閱讀 3442·2019-08-29 16:27
閱讀 2011·2019-08-29 16:11
閱讀 1038·2019-08-29 14:17
閱讀 2447·2019-08-29 13:47
閱讀 2024·2019-08-29 13:28