[JS] Symbols 的使用
let uniqueSymbol = Symbol('<key>');
let sharedSymbol = Symbol.for('<key>');
Symbol.keyFor('<SYMBOL>'); // 取得該 Symbol 的 Key
觀念
- ES6 引入了一種新的原始數據(primitive type)類型
Symbol
,表示獨一無二的值。它是 JavaScript 語言的第七種數據類型,前六種是:Undefined
、Null
、Boolean
、String
、Number
、Object
。 - 透過
symbol
建立的值都是獨特的(unique),因此可以作為獨特不重複的物件屬性名稱。 - 以 Symbol 為鍵的物件屬性與陣列元素類似,不能被類似
obj.name
的點運算符存取,你必須使用方括號[]
訪問這些屬性。 - Symbol 作為屬性名,該屬性不會出現在
for...in
、for...of
迴圈中,也不會被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。但是,它也不是私有屬性,有一個Object.getOwnPropertySymbols
方法,可以獲取指定對象的所有 Symbol 屬性名。 - 另一個新的 API,
Reflect.ownKeys
方法可以返回所有類型的鍵名,包括常規鍵名和 Symbol 鍵名。 - 由於以 Symbol 值作為名稱的屬性,不會被 常規方法遍歷得到。我們可以利用這個特性,為對象定義一些非私有的、但又希望只用於內部的方法。
建立 Symbol
建立 Symbol 不需要 new
。:
let symbol = Symbol('<key>');
console.log(typeof symbol); // symbol
Symbol(), Symbol.for(),Symbol.keyFor()
- 我們希望重新使用同一個 Symbol 值,
Symbol.for
方法可以做到這一點 Symbol()
:內部會建立一個獨特的 id(unique id) ,兩個相同 key 的 Symbol 是不同的,且無法透過Symbol.keyFor()
找到。Symbol.for()
:一樣都會生成新的 Symbol,但兩個相同 key 的 Symbol 會是相同的(reused id),且可以透過Symbol.keyFor()
找到。Symbol.keyFor()
方法返回一個已登記的 Symbol 類型值的 key。
/**
* Symbol() 每次都是新的,兩次生成的並不"相同",無法在全域被搜尋。
* Symbol.for() 兩次生成的會是相同的,可以在全域被 Symbol.keyFor() 搜尋到。
**/
let a = Symbol('Symbol A');
let aa = Symbol('Symbol A');
let b = Symbol.for('Symbol B');
let bb = Symbol.for('Symbol B');
a === aa; // false
b === bb; // true
透過 Symbol.keyFor()
取得某登記過的 symbol 鍵名
/**
* 使用 Symbol.keyFor() 查看某一變數的 Symbol
**/
Symbol.keyFor(a); // undefined
Symbol.keyFor(aa); // undefined
Symbol.keyFor(b); // Symbol B
Symbol.keyFor(bb); // Symbol B
See the Pen ES6 Symbol Demo Code by PJCHEN (@PJCHENder) on CodePen.