摘要:數據類型基本用法提供了一種類似于數組的新的數據結構。實例屬性和方法本身是一個構造函數,用來生成數據結構。返回一個布爾值,表示該值是否為的成員。任何具有接口且每個成員都是一個雙元素的數組的數據結構都可以當作構造函數的參數。
Set數據類型
基本用法
ES6 提供了一種類似于數組的新的數據結構 Set。它的成員的值都是唯一的,沒有重復的值。
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 結構轉為數組。 Array.from(items) //[1, 2, 3, 4, 5]
有沒有很開心?想想之前數組去重要雙重循環、indexOf各種判斷!用這個進行數組去重是不是很爽?
但是要注意:
向 Set 加入值的時候,不會發生類型轉換,所以5和"5"是兩個不同的值。Set 內部判斷兩個值是否不同,使用的算法叫做“Same-value-zero equality”,它類似于精確相等運算符(===),主要的區別是向 Set 加入值時認為NaN等于自身,而精確相等運算符認為NaN不等于自身。
實例屬性和方法
Set本身是一個構造函數,用來生成 Set 數據結構。
實例屬性
Set.prototype.constructor:構造函數,默認就是Set函數。
Set.prototype.size:返回Set實例的成員總數。
實例方法
Set 實例的方法分為兩大類:操作方法(用于操作數據)和遍歷方法(用于遍歷成員)
1、操作方法
Set.prototype.add(value):添加某個值,返回 Set 結構本身。
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():使用回調函數遍歷每個成員,沒有返回值。
由于 Set 結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),所以keys方法和values方法的行為完全一致。
WeakSet數據類型WeakSet與Set數據結構類似,但是有2個不同點。
1、WeakSet 的成員只能是對象,而不能是其他類型的值
2、WeakSet 中的對象都是弱引用。如果其他對象都不再引用該對象,那么垃圾回收機制會自動回收該對象所占用的內存,不考慮該對象還存在于 WeakSet 之中。
由于上面這個特點,WeakSet 的成員是不適合引用的,因為它會隨時消失。另外,由于 WeakSet 內部有多少個成員,取決于垃圾回收機制有沒有運行,運行前后很可能成員個數是不一樣的,而垃圾回收機制何時運行是不可預測的,因此 ES6 規定 WeakSet 不可遍歷。也就沒有size屬性。
WeakSet 結構有三個方法。
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的實例上調用!"); } } }
上面代碼保證了Foo的實例方法,只能在Foo的實例上調用。這里使用 WeakSet 的好處是,foos對實例的引用,不會被計入內存回收機制,所以刪除實例的時候,不用考慮foos,也不會出現內存泄漏。
Map數據類型基本用法
由于ES5的Object提供的hash(鍵值對)里只能用字符串當作鍵,會有很大的限制。所以ES6提供了更接近hash結構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 接口、且每個成員都是一個雙元素的數組的數據結構都可以當作Map構造函數的參數。這就是說,Set和Map都可以用來生成新的 Map。
//數組 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 結構才將其視為同一個鍵。
3、Map 的鍵如果是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map 將其視為一個鍵,比如0和-0就是一個鍵,布爾值true和字符串true則是兩個不同的鍵。另外,undefined和null也是兩個不同的鍵。雖然NaN不嚴格相等于自身,但 Map 將其視為同一個鍵。
new Map().get("asfddfsasadf") // undefined const map = new Map(); map.set(["a"], 555); map.get(["a"]) // undefined
實例的屬性和方法
實例屬性
size屬性返回 Map 結構的成員總數。
const map = new Map(); map.set("foo", true); map.set("foo", false); map.size // 1
方法
1、操作方法
Map.prototype.set(key, value);設置鍵名key對應的鍵值為value;會覆蓋原值
Map.prototype.get(key);讀取key對應的鍵值,找不到會返回undefined。
Map.prototype.has(key);表示某個鍵是否在當前 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 的遍歷順序就是插入順序
與其他數據結構的互相轉換
(1)Map 轉為數組
Map 轉為數組最方便的方法,就是使用擴展運算符(...)。
const myMap = new Map() .set(true, 7) .set({foo: 3}, ["abc"]); [...myMap] // [ [ true, 7 ], [ { foo: 3 }, [ "abc" ] ] ]
(2)數組 轉為 Map
將數組傳入 Map 構造函數,就可以轉為 Map。
new Map([ [true, 7], [{foo: 3}, ["abc"]] ]) // Map { // true => 7, // Object {foo: 3} => ["abc"] // }
(3)Map 轉為對象
如果所有 Map 的鍵都是字符串,它可以無損地轉為對象。
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 }
如果有非字符串的鍵名,那么這個鍵名會被轉成字符串,再作為對象的鍵名。
(4)對象轉為 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 轉為 JSON
Map 轉為 JSON 要區分兩種情況。一種情況是,Map 的鍵名都是字符串,這時可以選擇轉為對象 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 的鍵名有非字符串,這時可以選擇轉為數組 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 轉為 Map
JSON 轉為 Map,正常情況下,所有鍵名都是字符串。
function jsonToStrMap(jsonStr) { return objToStrMap(JSON.parse(jsonStr)); } jsonToStrMap("{"yes": true, "no": false}") // Map {"yes" => true, "no" => false}
但是,有一種特殊情況,整個 JSON 就是一個數組,且每個數組成員本身,又是一個有兩個成員的數組。這時,它可以一一對應地轉為 Map。這往往是 Map 轉為數組 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結構與Map結構類似,但是有兩點區別:
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 應用的典型場合就是 DOM 節點作為鍵名。下面是一個例子。
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 節點,每當發生click事件,就更新一下狀態。我們將這個狀態作為鍵值放在 WeakMap 里,對應的鍵名就是myElement。一旦這個 DOM 節點刪除,該狀態就會自動消失,不存在內存泄漏風險。
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類的兩個內部屬性_counter和_action,是實例的弱引用,所以如果刪除實例,它們也就隨之消失,不會造成內存泄漏。
參考文章
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105594.html
摘要:但是有了尾調用優化之后,遞歸函數的性能有了提升。常被用來檢查對象中是否存在某個鍵名,集合常被用來獲取已存的信息。循環解構對象本身不支持迭代,但是我們可以自己添加一個生成器,返回一個,的迭代器,然后使用循環解構和。 一、let和const 在JavaScript中咱們以前主要用關鍵var來定義變量,ES6之后,新增了定義變量的兩個關鍵字,分別是let和const。對于變量來說,在ES5中...
摘要:經常會用到的的知識點提到我們就來說說,也是誕生,它的初始名叫。又名,在,和大受重用。年,負責制定規范草案的委員會決定將定義新標準的制度改為一年一次出現。它們在規范的先前版本中被稱為模板字符串。它與數組非常相似,但是數據結構的成員都是唯一的。 經常會用到的es6的知識點 提到es6我們就來說說javascript,es6也是ES2015 1995:JavaScript誕生,它的初始名叫...
摘要:執行函數會返回一個遍歷器對象,每一次函數里面的都相當一次遍歷器對象的方法,并且可以通過方法傳入自定義的來改變函數的行為。函數可以通過配合函數更輕松更優雅的實現異步編程和控制流管理。它和構造函數的不同點類的內部定義的所有方法,都是不可枚舉的。 let const的命令 在ES6之前,聲明變量只能用var,var方式聲明變量其實是很不合理的,準確的說,是因為ES5里面沒有塊級作用域是很不合...
摘要:前言新增了兩種基本的原生數據集合和加上和現在共有四種,以及由兩者衍生出的弱引用集合和。其本身是生成實例數據集合的構造函數,可以接受一個數組或具有接口的數據結構作為參數用來初始化。返回鍵值對的遍歷器對象,鍵值對為鍵名鍵值。 前言 ES6新增了兩種基本的原生數據集合:Set和Map(加上Array和Object現在共有四種),以及由兩者衍生出的弱引用集合:WeakSet和WeakMap。從...
摘要:新增了數據結構,對象保存鍵值對,任何值原始值或對象都可以作為一個鍵或一個值。基本用法實例的屬性和操作方法方法設置鍵名對應的鍵值為,然后返回整個結構。獲取的值方法返回一個布爾值,表示某個鍵是否在當前對象之中。如果刪除失敗,返回。 ES6新增了 Map數據結構,Map對象保存鍵值對,任何值(原始值或對象)都可以作為一個鍵或一個值。 基本用法 let map = new Map(); let...
閱讀 766·2023-04-25 17:33
閱讀 3626·2021-07-29 14:49
閱讀 2480·2019-08-30 15:53
閱讀 3435·2019-08-29 16:27
閱讀 2000·2019-08-29 16:11
閱讀 1030·2019-08-29 14:17
閱讀 2432·2019-08-29 13:47
閱讀 2016·2019-08-29 13:28