Js基礎知識7-Es6新增對象Map和set數據結構
前言
JavaScript中對象的本質是鍵值對的集合,ES5中的數據結構,主要是用Array和Object,但是鍵只能是字符串。為了彌補這種缺憾,ES6帶來了一種新的數據結構Map。
Map也是鍵值對的集合,只是鍵不僅可以是字符串還可以是其他數據類型,比如:對象(是不是很神奇)。請看下面例子。。下面話不多說了,來一起看看詳細的介紹吧。
Map 對象
Map結構提供了“值—值”的對應,任何值(對象或者原始值) 都可以作為一個鍵或一個值,是一種更完善的Hash結構實現。如果你需要“鍵值對”的數據結構,Map比Object更合適。它類似於對象,也是鍵值對的集合,但是“鍵”的範圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。
屬性
Map屬性
-
Map.length 屬性length的值為0。
-
Map.prototype 表示Map構造器的原型。允許添加屬性從而應用與所有的Map對象
Map實例 - 所有Map對象的實例都會繼承Map.prototype。
-
Map.prototype.constructor 返回創建給map實例的構造函數,默認是Map函數。
-
Map.prototype.size 返回Map對象的鍵值對的數量。
var map = new Map([[‘one‘,1], [‘two‘, 2], [‘three‘, 3]]); console.log(map.constructor);//function Map() { [native code] } console.log(map.size); //3
方法
//Iterator對象:可以使用for..of進行叠代的對象 var map = new Map([[1, ‘one‘],[2, ‘two‘], [3, ‘three‘]]);
1.Map.prototype.set(key, value) 設置Map對象中鍵的值,返回該Map對象。
console.log(map.has(4)); //false map.set(4, ‘four‘); console.log(map.has(4)) //true
2.Map.prototype.get(key) 返回鍵對應的值,如果不存在,則返回undefined。
map.get(1); //‘one‘
3.Map.prototype.has(key) 返回一個布爾值,表示Map實例是否包含鍵對應的值。
map.has(1); // true
map.has(5); //false
4.Map.prototype.delete(key) 移除任何與鍵相關聯的值,並且返回該值,該值在之前會被Map.prototype.has(key)返回為true。之後再調用則返回false。
console.log(map.has(1)); //true
map.delete(1);
console.log(map.has(1)); //false
5.Map.prototype.clear() 移除Map對象的所有鍵值對。
console.log(map.size); //3
map.clear();
console.log(map.size); //0
6.Map.prototype.entries() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每個元素的[key, value]數組。
console.log(map); //Map {1 => "one", 2 => "two", 3 => "three"}
map.entries();
console.log(map); //Map {1 => "one", 2 => "two", 3 => "three"}
7.Map.prototype.forEach(callbackFn[, thisArg]) 按插入順序,為Map對象裏的每一鍵值對調用一次callbackFn函數。如果為forEach提供了thisArg,他將在每次回調函數中作為this值。
map.forEach(function(value, key, mapObj) {
console.log(value + ‘---‘ + key + ‘---‘ + mapObj);
//value - Map對象裏每一個鍵值對的值
//key - Map對象裏每一個鍵值對的鍵
//mapObj - Map對象本身
console.log(this); //this === window
});
map.forEach(function(value, key, mapObj) {
console.log(value + ‘---‘ + key + ‘---‘ + mapObj);
console.log(this); //this === map
}, map)
8.Map.prototype.keys() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每個元素的鍵。
map.keys(); //MapIterator {1, 2, 3}
9.Map.prototype.values() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每個元素的值。
map.values(); //
使用for..of方法叠代映射
var map = new Map();
map.set(1, ‘one‘);
map.set(2, ‘two‘);
for (var [key, value] of map) {
console.log(key + ‘---‘ + value);
}
// 1 --- one 2 --- two
for (var key of map.keys()) {
console.log(key);
}
// 1 2
for (var value of map.values()) {
console.log(value);
}
// ‘one‘ ‘two‘
常規用法綜合
var map = new Map(); //創建map對象 map.set(‘one‘, 1); map.set(‘two‘, 2); map.set(‘three‘, 3); //或者 var map = new Map([[‘one‘,1], [‘two‘, 2], [‘three‘, 3]]); m.set(ul,‘content‘); //為Map增加成員 m.get(ul);//獲取鍵 ul對應的值 m.has(ul);//返回布爾值,判斷是否含有鍵 ul m.delete(ul);//刪除鍵 ul,成功返回true,失敗返回false m.size //返回m長度 m.clear(); //清除m所有成員
Map VS Object
-
一個對象通常都有自己的原型,所以一個對象總有一個"prototype"鍵。不過,從ES5開始可以使用map = Object.create(null)來創建一個沒有原型的對象。
-
一個對象的鍵只能是字符串或者Symbols,但一個Map的鍵可以是任意值。
-
你可以通過size屬性很容易地得到一個Map的鍵值對個數,而對象的鍵值對個數只能手動確認。
數據類型轉換
...擴展語句
擴展語法允許一個表達式在期望多個參數(用於函數調用)或多個元素(用於數組字面量)或多個變量(用於解構賦值)的位置擴展。
let arr1 = [0, 1, 2]; let arr2 = [3, 4, 5]; arr1 = [...arr2, ...arr1]; console.log(arr1) // [3, 4, 5, 0, 1, 2]
Map轉數據的最簡單方式是使用 ... 擴展運算符。例如:
var map = new Map([[‘one‘,1], [‘two‘, 2], [‘three‘, 3]]); console.log(...map); //["one", 1] ["two", 2] ["three", 3]
Map轉對象時,必須所有鍵都是字符串,使用Object.create()函數。Map轉JSON時,要求也要求所有鍵都是字符串,使用JSON.Stringify()函數。
需要註意的
1、轉換時註意
2、當鍵是對象時,必須是引用相同,才認為鍵是相同的。只有對同一個對象的引用,Map結構才將其視為同一個鍵。這一點要非常小心。
var map = new Map(); map.set([‘a‘], 555); map.get([‘a‘]) // undefined //上面代碼的set和get方法,表面是針對同一個鍵,但實際上這是兩個值,內存地址是不一樣的,因此get方法無法讀取該鍵,返回undefined。
3、如果Map的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map將其視為一個鍵,包括0和-0。另外,雖然NaN不嚴格相等於自身,但Map將其視為同一個鍵。
var map = new Map(); map.set(Number(‘aa111‘), ‘isNaN‘); map.set(Number(‘bb222‘), ‘also is NaN‘); map.get(NaN); //‘also is NaN‘
Set 對象
簡要
ES6提供了新的數據結構Set。它類似於數組,但是成員的值都是唯一的,沒有重復的值。
Set函數可以接受一個數組(或類似數組的對象)作為參數,用來初始化。
Set對象允許你存儲任意類型的唯一值(不能重復),無論它是原始值或者是對象引用。
Set本身是一個構造函數,用來生成Set數據結構。
Set結構有以下屬性:
- Set.prototype.constructor: 構造函數,默認就是Set函數。
- set.prototype.size : 返回Set的成員總數。
Set結構有以下方法:
- add(value) : 添加某個值,返回Set結構本身。
- delete(value) : 刪除某個值,返回一個布爾值,表示是否成功。
- has(value) : 返回一個布爾值,表示該值是否為Set的成員。
- clear() : 清除所有成員,沒有返回值。
Set遍歷操作:
- keys():返回鍵名的遍歷器
- values(): 返回健值對的遍歷器
- entries():返回鍵值對的遍歷器
- forEach(): 每個成員
Set屬性
-
Set.length 屬性length的值為0。
-
Set.prototype 表示Set構造器的原型。允許向所有Set對象添加新的屬性。
Set實例
所有Set對象的實例都會繼承Set.prototype。
-
Set.prototype.constructor 返回創建給set實例的構造函數,默認是Set函數。
-
Set.prototype.size 返回Set對象的鍵值對的數量。
var sset = new Set([‘one‘, ‘two‘, ‘three‘]);
console.log(sset.constructor); //function Set() { [native code] }
console.log(sset.size); //3
Set方法
//創建Set實例
//1.
var sset = new Set();
sset.add(‘one‘);
sset.add(‘two‘);
sset.add(‘three‘);
//2.
var sset= new Set([‘one‘, ‘two‘, ‘three‘]);
1.Set.prototype.add(value) 在Set對象尾部添加一個元素。返回該Set對象。
sset.add(‘four‘);
console.log(sset); //Set {"one", "two", "three", "four"}
2.Set.prototype.clear() 移除Set對象內的所有元素。
sset.clear();
console.log(sset.size); //0
3.Set.prototype.delete(value) 移除Set的中與這個值相等的元素,返回Set.prototype.has(value)在這個操作前會返回的值(即如果該元素存在,返回true,否則返回false)。Set.prototype.has(value)在此後會返回false。
console.log(sset.has(‘one‘)); //true
sset.delete(‘one‘);
console.log(sset.has(‘one‘)); //false
4.Set.prototype.entries() 返回一個新的叠代器對象,該對象包含Set對象中的按插入順序排列的所有元素的值的[value, value]數組。為了使這個方法和Map對象保持相似, 每個值的鍵和值相等。
5.Set.prototype.forEach(callbackFn[, thisArg]) 按照插入順序,為Set對象中的每一個值調用一次callBackFn。如果提供了thisArg參數,回調中的this會是這個參數。
sset.forEach(function(value, key, setObj) {
console.log(value + ‘---‘ + key + ‘---‘ + setObj);
//value - Set對象裏每一個鍵值對的值
//key - Set對象裏每一個鍵值對的鍵 === 值
//mapObj - Set對象本身
console.log(this); //this === window
});
sset.forEach(function(value, key, setObj) {
console.log(value + ‘---‘ + key + ‘---‘ + setObj);
console.log(this); //this === sset
}, sset)
6.Set.prototype.has(value) 返回一個布爾值,表示Map實例是否包含鍵對應的值。
sset.has(‘one‘); // true
sset.has(‘fivr‘); //false
7.Set.prototype.keys() 與values()方法相同,返回一個新的叠代器對象,該對象包含Set對象中的按插入順序排列的所有元素的值。
sset.keys(); //SetIterator {"one", "two", "three"}
8.Set.prototype.values() 返回一個新的Iterator對象,它按插入順序包含了Map對象中每個元素的值。
sset.values(); //SetIterator {"one", "two", "three"}
使用for..of方法叠代映射
var sset = new Set();
sset.add(1);
sset.add(2);
for (var value of sset) {
console.log(value);
}
// 1 2
for (var key of sset.keys()) {
console.log(key);
}
// 1 2
for (var value of sset.values()) {
console.log(value);
}
// 1 2
Set 與 Array
var myArray = ["value1", "value2", "value3"]; // 用Set構造器將Array轉換為Set var mySet = new Set(myArray); mySet.has("value1"); // returns true // 用...(展開操作符)操作符將Set轉換為Array console.log([...mySet]); // 與myArray完全一致
Array.from方法可以將Set結構轉換為數組。
var items = new Set([1, 2, 3, 4, 5]); var array = Array.from( items );
這也提供了一種除去數組中重復元素的方法。
function dedupe( array ) { return Array.from( new Set(array) ); }
或者如下寫也可以,比較簡單的數組去重
[...new Set([1,3,4,5,1,2,3,3,4,8,90,3,0,5,4,0])]
Set 註意
1、var sset = new Set(‘one‘, ‘two‘, ‘three‘); //這樣的錯誤的
2、值的相等規則:NaN 是與NaN是相同的(雖然NaN !== NaN),除此之外所有的值都根據‘===‘判斷。
var sset= new Set(); sset.add(Number(‘aa111‘)); sset.add(Number(‘bb222‘)); sset.add(‘cc333‘)); //Set {NaN, "cc333"}
3、向Set加入值的時候,不會發生類型轉換。這意味著,在Set中5和”5”是兩個不同的值。
weakset對象
WeakSet結構與Set類似,也是不重復的值的集合。
WeakSet和Set的區別:
- 1.WeakSet的成員只能是對象,而不能是其他類型的值
- 2.WeakSet中的對象都是弱引用,即垃圾回收機制不考慮WeakSet對該對象的引用,也就是說,如果其他對象都不再引用該對象,那麽垃圾回收機制會自動回收該對象所占用的內存,不考慮該對象還存在於WeakSet之中。這個特點意味著,無法引用WeakSet的成員,因此WeakSet是不可遍歷的。
WeakSet結構的三個方法
add
delete
has
WeakSet的一個用處是儲存DOM節點,而不用擔心這些節點會從文檔中移除時,會引發內存泄露。
Js基礎知識7-Es6新增對象Map和set數據結構