ES6新增的Symbol

由來
ES5 的對象屬性名都是字符串,這容易造成屬性名的衝突。比如,你使用了一個他人提供的對象,但又想爲這個對象添加新的方法(mixin 模式),新方法的名字就有可能與現有方法產生衝突。如果有一種機制,保證每個屬性的名字都是獨一無二的就好了,這樣就從根本上防止屬性名的衝突。這就是 ES6 引入Symbol的原因。

基礎數據類型
ES6中引入了一種新的數據類型symbol,表示獨一無二的值。它是JS的第七種基礎數據類型,前六種分別爲:undefined、null、Boolean、String、Number、Object
由於Symbol是一種基礎數據類型,所以當我們使用typeof去檢查它的類型的時候,它會返回一個屬於自己的類型symbol

let s = Symbol()
typeof s // "symbol"

我們可以通過調用Symbol()函數來創建一個Symbol實例,但是不能用 new 命令,因爲 Symbol 是原始數據類型,不是對象。

可選參數
Symbol()可以接受一個字符串作爲參數,爲新創建的 Symbol 提供描述,用來顯示在控制檯或者作爲字符串的時候使用,便於區分。

let sym = Symbol('zlear')
let sym2 = Symbol()
sym // Symbol(zlear)
sym2 // Symbol()

ES2019 提供了一個實例屬性description,直接返回 Symbol 的描述

let sym = Symbol('fedezer');
sym.description // "fedezer"

注意,Symbol函數的參數只是表示對當前 Symbol 值的描述,因此相同參數的Symbol函數的返回值是不相等的。

// 沒有參數的情況
let s1 = Symbol();
let s2 = Symbol();

s1 === s2 // false

// 有參數的情況
let s1 = Symbol('foo');
let s2 = Symbol('foo');

s1 === s2 // false

唯一性
對象的屬性名現在可以有兩種類型,一種是原來就有的字符串,另一種就是新增的 Symbol 類型。凡是屬性名屬於 Symbol 類型,就都是獨一無二的,可以保證不會與其他屬性名產生衝突。

var a={}, b=Symbol('123'), c=Symbol('123');  
a[b]='b';
a[c]='c';  

a[b] // 'b'
a[c] // 'c'
a // {Symbol(123): "b", Symbol(123): "c"}

順便拓展瞭解一下鍵名:

  • 對象的鍵名只能是字符串和 Symbol 類型。
  • 其他類型的鍵名會被轉換成字符串類型。
  • 對象轉字符串默認會調用 toString 方法。

屬性名
Symbol 作爲屬性名,但該屬性不會出現在for…in、for…of循環中,也不會被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。

let obj = {
   [Symbol('name')]: 'Zlear',
   age: 18,
   sex: 'woman'
}

Object.keys(obj)   // ['age', 'sex']

for (let p in obj) {
   console.log(p)   // 分別會輸出:'age' 和 'sex'
}

Object.getOwnPropertyNames(obj)   // ['age', 'sex']

JSON.stringify(obj) // {"age":18,"title":"Engineer"}

Object.getOwnPropertySymbols方法,可以獲取指定對象的所有 Symbol 屬性名

Object.getOwnPropertySymbols(obj) // [Symbol(name)]

阮一峯 ECMAScript 6 入門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章