ES6才加入的primitive type
,我個人覺得是primitive type
當中最難理解的。
object
的key
在ES6之前都只能是字串,就算寫成數字也會被轉成字串,所以之前我會說,object
的key
只能是字串,但這個說法被symbol
打破了,它也可以拿來當作object
的key
,而它為什麼可以,以及symbol
是處理什麼領域的問題,讓我們看下去吧。
symbol
可以直接跟獨一無二的值劃上等號,只會有一個保證是唯一的,這其實就是可以拿來當作object
的key
的原因,不會重複很適合拿來幫物件取名。
這樣記:只要透過symbol
建立的值,都會獲得特性:獨一無二
。
建立symbol
的方式很簡單,只要使用Symbol()
即可,不需要用new
。
// 語法
const fruit = Symbol();
console.log(typeof symbol); // symbol
可以給Symbol
裡面加名字,在Symbol()
的()
裡面,可以當作它是這個變數fruit
的描述,而它的類別是Symbol
。
由於特性:獨一無二
,所以當名字都是取一樣的,實際上值也是不同的,名字僅供參考,像是:
const fruit = Symbol("apple");
const fruit2 = Symbol("apple");
console.log(fruit == fruit2); // false
所有的Symbol
都是不同的,就算名字都取的一樣,但有時候還是會想要說相同名字的Symbol
能夠擁有相同的實體,為了做到這件事情,需要一個名為global Symbol registry
的概念。
想像有一個神秘的空間(註冊表),創建了Symbol
會註冊在裡面,想去看的時後可以隨時訪問,但不是想看就看的,需要名為招式Symbol.for()
才辦到的。
要在註冊表裡讀取symbol
,需要使用Symbol.for()
。
Symbol.for()
相當於創立Symbol
,只是這個創立Symbol
是把它放到註冊表當中。
const fruit = Symbol.for("apple");
const fruit2 = Symbol.for("apple");
console.log(fruit == fruit2); // true
比較一下:Symbol()
=> 每個創立都不相同(就算同名字),全域無法找到。Symbol.for()
=> 創立時會放到註冊表,同名字就當作相同創建,在全域可以被Symbol.keyFor()
找到。
而我要怎麼去拿到已經放到在註冊表裡面的symbol
?
就會需要另一個招式=> Symbol.keyFor()
const fruit = Symbol("apple");
const fruit2 = Symbol.for("apple");
console.log(Symbol.keyFor(fruit)); // undefined
console.log(Symbol.keyFor(fruit2)); // apple
一樣直接創立的話,就不存在於global Symbol registry
,自然Symbol.keyFor()
就無法找到。
這兩個招式其實就是symbol
的Static methods
(靜態方法)。
可能是symbol
太有個性了(獨一無二),在某些場合,會發生symbol
被無視的狀況,比如說for..in
:
const fruit = Symbol("apple");
const user = {
name: "vic",
age: 23,
[fruit]: "this is a apple",
};
for (const key in user) console.log(key); // name, age 沒有 fruit
不過還是能找到它裡面的值:
console.log(user[fruit]); // this is a apple
跟for..in
同個系列的for..of
也會被略過。
另外一個會排擠symbol
是Object.keys
:
遇到就直接無視。
const fruit = Symbol("apple");
const obj = {
a: 1,
b: 2,
[fruit]: "this is a apple",
};
console.log(Object.keys(obj)); // [ 'a', 'b' ]
symbol
在for..in
、for..of
、Object.keys
都會被跳過。
可以反過來利用這個特性,當你想要隱藏某一些物件的屬性時,用symbol
當object
的key
就對了,它在上面那些狀況都不會與其他属性一起被處理。
[1] MDN - Symbol
[2] JS Symbols 的使用
[3] ECMAScript 6 入門