ES6語法之Symbol

概述

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

ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。它是 JavaScript 語言的第七種數據類型,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數值(Number)、對象(Object)。app

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

Symbol 是一種獨特的且不可變的數據類型,常常用來標識對象屬性。code

要建立 Symbol,輸入 Symbol(),並添加一個可選的字符串做爲其描述。對象

const sym1 = Symbol('apple');
console.log(sym1); //Symbol(apple)

它將建立惟一的標識符,並將其存儲在 sym1 中。描述 "apple" 只是用來描述標識符的一種方式,可是不能用來訪問標識符自己。ip

若是對具備相同描述的兩個標識符進行比較……字符串

const sym2 = Symbol('banana');
const sym3 = Symbol('banana');
console.log(sym2 === sym3);

結果是 false,由於描述只是用來描述符號,它並非標識符自己的一部分。不管描述是什麼,每次都建立新的標識符。get

Symbol 值不能與其餘類型的值進行運算,會報錯。可是,Symbol 值能夠顯式轉爲字符串。也能夠轉爲布爾值,可是不能轉爲數值。string

let sym = Symbol('My symbol');

"your symbol is " + sym  // TypeError: can't convert symbol to string

String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'

Boolean(sym) // true
!sym  // false

Number(sym) // TypeError
sym + 2 // TypeError

做爲屬性名的 Symbol

因爲每個 Symbol 值都是不相等的,這意味着 Symbol 值能夠做爲標識符,用於對象的屬性名,就能保證不會出現同名的屬性
let mySymbol = Symbol();

// 第一種寫法
let a = {};
a[mySymbol] = 'Hello!';

// 第二種寫法
let a = {
    [mySymbol]: 'Hello!'
 };
 
 a[mySymbol] // "Hello!"

注意,Symbol 值做爲對象屬性名時,不能用點運算符。同理,在對象的內部,使用 Symbol 值定義屬性時,Symbol 值必須放在方括號之中。console

屬性名的遍歷

Symbol 做爲屬性名,該屬性不會出如今for...in、for...of循環中,也不會被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。可是,它也不是私有屬性,有一個Object.getOwnPropertySymbols方法,能夠獲取指定對象的全部 Symbol 屬性名。class

const obj = {};
let a = Symbol('a');
let b = Symbol('b');

obj[a] = 'Hello';
obj[b] = 'World';

const objectSymbols = Object.getOwnPropertySymbols(obj);

objectSymbols
// [Symbol(a), Symbol(b)]
相關文章
相關標籤/搜索