一辱匿、Symbol
ES6 引入了一種新的原始數據類型Symbol
,表示獨一無二的值炫彩。它是 JavaScript 語言的第七種數據類型匾七,前六種是:undefined
、null
江兢、布爾值(Boolean)昨忆、字符串(String)、數值(Number)杉允、對象(Object)邑贴。
注意點:
-
symbol
是一種基本數據類型(非復雜類型)。
- 它不支持語法
new Symbol()
夺颤。
- 每個從
Symbol()
返回的symbol
值都是唯一的痢缎。
Symbol的用途
- 一個
symbol
值能作為對象屬性的標識符。
由于每一個 Symbol 值都是不相等的世澜,這意味著 Symbol 值可以作為標識符独旷,用于對象的屬性名,就能保證不會出現同名的屬性寥裂。
let mySymbol = Symbol();
// 第一種寫法
let a = {};
a[mySymbol] = 'Hello!';
// 第二種寫法
let a = {
[mySymbol]: 'Hello!'
};
// 第三種寫法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上寫法都得到同樣結果
a[mySymbol] // "Hello!"
- 可以用
Symbol
來模擬私有屬性
例如嵌洼,我們可以在一個塊內使用Symbol
作為對象的屬性名
這樣在這個塊之外就無法訪問到我們用Symbol
定義的屬性
二、Set
ES6 以前實現數組去重(計數排序的邏輯)
function unique(arr) {
var hashTab = {}
var newArr
for (let i = 0; i < arr.length; i++) {
if (arr[i] in hashTab) {
// 什么也不做
} else {
hashTab[arr[i]] = true
}
}
newArr = Object.keys(hashTab).map(n => n - 0)
return newArr
}
但這種算法并不完美封恰,它存在兩個缺陷:
- 它無法區(qū)分數組中的數字和字符串
- 如果數組里有對象麻养,也會影響去重的結果
例如有一個數組
var a = [1, 2, 2, '5', 4, 5, 6, 6, 8, 8, 2, 3, {name: 'object'}]
我們期望對它去重后的結果為
[1, 2, 3, 4, 5, 6, 8, '5', {name: 'object'}]
但上面的代碼得不到我們想要的結果
ES6引入了一種新的數據結構Set
,它類似于數組诺舔,但是成員的值都是唯一的鳖昌,沒有重復的值。
另外低飒,兩個對象總是不相等的许昨。
上面代碼中,由于兩個空對象不相等褥赊,所以它們被視為兩個值糕档。但如果是對同一個對象的多次引用,則只被視為一個值拌喉。
Set 實例的屬性和方法
Set 結構的實例有以下屬性速那。
-
Set.prototype.constructor
:構造函數俐银,默認就是Set
函數。 -
Set.prototype.size
:返回Set
實例的成員總數端仰。
Set 實例的方法分為兩大類:操作方法(用于操作數據)和遍歷方法(用于遍歷成員)
- 操作方法:
-
Set.prototype.add(value)
:添加某個值捶惜,返回Set
結構本身。 -
Set.prototype.delete(value)
:刪除某個值荔烧,返回一個布爾值售躁,表示刪除是否成功。 -
Set.prototype.has(value)
:返回一個布爾值茴晋,表示該值是否為Set
的成員。 -
Set.prototype.clear()
:清除所有成員回窘,沒有返回值诺擅。
-
- 遍歷方法:
-
Set.prototype.keys()
:返回鍵名的遍歷器 -
Set.prototype.values()
:返回鍵值的遍歷器 -
Set.prototype.entries()
:返回鍵值對的遍歷器 -
Set.prototype.forEach()
:使用回調函數遍歷每個成員
-
s.add(1).add(2).add(2);
// 注意2被加入了兩次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
我們可以使用Set
來解決上面數組去重的問題
三、Map
JavaScript 的對象(Object)啡直,本質上是鍵值對的集合(Hash 結構)烁涌,但是傳統(tǒng)上只能用字符串當作鍵。這給它的使用帶來了很大的限制酒觅。
為了解決這個問題撮执,ES6 提供了 Map 數據結構。它類似于對象舷丹,也是鍵值對的集合抒钱,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當作鍵颜凯。
也就是說谋币,Object 結構提供了“字符串—值”的對應,Map 結構提供了“值—值”的對應症概,是一種更完善的 Hash 結構實現蕾额。
上面的例子展示了如何向 Map 添加成員。作為構造函數彼城,Map 也可以接受一個數組作為參數诅蝶。該數組的成員是一個個表示鍵值對的數組。
Map的遍歷方法
Map 結構原生提供三個遍歷器生成函數和一個遍歷方法募壕。
-
Map.prototype.keys()
:返回鍵名的遍歷器调炬。 -
Map.prototype.values()
:返回鍵值的遍歷器。 -
Map.prototype.entries()
:返回所有成員的遍歷器司抱。 -
Map.prototype.forEach()
:遍歷 Map 的所有成員筐眷。
四、WeakSet
WeakSet 結構與 Set 類似习柠,也是不重復的值的集合匀谣。但是照棋,它與 Set 有兩個區(qū)別。
1. WeakSet 的成員只能是對象武翎,而不能是其他類型的值
2. WeakSet 中的對象都是弱引用
垃圾回收機制不考慮 WeakSet 對該對象的引用烈炭,也就是說,如果其他對象都不再引用該對象宝恶,那么垃圾回收機制會自動回收該對象所占用的內存符隙,不考慮該對象還存在于 WeakSet 之中
上面的代碼中垫毙,當我們把對象a
置為null
之后霹疫,通常的理解是此時還有一個WeakSet
引用著對象a
,因此a
所指向的內存不會被標記為垃圾综芥,從而不會被回收丽蝎。
但事實上,前面說過WeakSet
是弱引用膀藐,當把a
置為null
之后屠阻,可以理解為此時WeakSet對a
所指向的內存的引用就消失了,因此會正常的進行垃圾回收额各。
五国觉、WeakMap
WeakMap
結構與Map
結構類似,也是用于生成鍵值對的集合虾啦。WeakMap
與Map
的區(qū)別有兩點麻诀。
1. WeakMap只接受對象作為鍵名(null除外),不接受其他類型的值作為鍵名
2. WeakMap的鍵名所指向的對象缸逃,不計入垃圾回收機制
WeakMap
的設計目的在于针饥,有時我們想在某個對象上面存放一些數據,但是這會形成對于這個對象的引用需频。
const e1 = document.getElementById('foo');
const e2 = document.getElementById('bar');
const arr = [
[e1, 'foo 元素'],
[e2, 'bar 元素'],
];
上面代碼中丁眼,e1
和e2
是兩個對象,我們通過arr
數組對這兩個對象添加一些文字說明昭殉。這就形成了arr
對e1
和e2
的引用苞七。
一旦不再需要這兩個對象,我們就必須手動刪除這個引用挪丢,否則垃圾回收機制就不會釋放e1
和e2
占用的內存蹂风。
// 不需要 e1 和 e2 的時候
// 必須手動刪除引用
arr [0] = null;
arr [1] = null;
上面這樣的寫法顯然很不方便。一旦忘了寫乾蓬,就會造成內存泄露惠啄。
WeakMap
就是為了解決這個問題而誕生的,它的鍵名所引用的對象都是弱引用,即垃圾回收機制不將該引用考慮在內撵渡。因此融柬,只要所引用的對象的其他引用都被清除,垃圾回收機制就會釋放該對象所占用的內存趋距。也就是說粒氧,一旦不再需要,WeakMap
里面的鍵名對象和所對應的鍵值對會自動消失节腐,不用手動刪除引用外盯。
基本上,如果你要往對象上添加數據翼雀,又不想干擾垃圾回收機制饱苟,就可以使用WeakMap
。一個典型應用場景是狼渊,在網頁的 DOM 元素上添加數據掷空,就可以使用WeakMap
結構。當該 DOM 元素被清除囤锉,其所對應的WeakMap
記錄就會自動被移除。
const wm = new WeakMap();
const element = document.getElementById('example');
wm.set(element, 'some information');
wm.get(element) // "some information"
上面代碼中护锤,先新建一個WeakMap
實例官地。然后,將一個 DOM 節(jié)點作為鍵名存入該實例烙懦,并將一些附加信息作為鍵值驱入,一起存放在WeakMap
里面。這時氯析,WeakMap
里面對element的引用就是弱引用亏较,不會被計入垃圾回收機制。
總之掩缓,WeakMap
的專用場合就是雪情,它的鍵所對應的對象挠轴,可能會在將來消失践瓷。WeakMap
結構有助于防止內存泄漏瘪贱。
以上只是對WeakMap的簡單介紹蒸甜,如果你想深入學習WeakMap請看這篇文章ES2015 WeakMap的學習和使用
如果想了解內存泄漏請看文章JavaScript 內存泄漏教程