Symbol
是ES6
中新引入的一種基本數據類型。Symbol()
函數會返回 symbol 類型的值,該類型具備靜態屬性和靜態方法。它的靜態屬性會暴露幾個內建的成員對象;它的靜態方法會暴露全局的 symbol 註冊,且相似於內建對象類,但做爲構造函數來講它並不完整,由於它不支持語法:new Symbol()
。javascript
也就是說Symbol
做爲一種新的基本數據類型,咱們能夠使用:java
let a = Symbol();
複製代碼
此時a
即是一個Symbol
類型的變量,它如今是獨一無二的:數組
let b = Symbol();
a === b; //false
複製代碼
它還能夠接受一個參數,咱們能夠給它傳遞一個字符串當描述,即便兩個字符相同串也ok:函數
let symbol1 = Symbol('some');
let symbol2 = Symbol('some');
symbol1 === symbol2; //false
複製代碼
若是參數是對象的話,會先調用對象的toString
方法來轉換爲字符串。 也就是說每個Symbol
創造出來的值都是不同的。須要注意的是不能使用new
的方式來建立:ui
let c = new Symbol(); //TypeError: Symbol is not a constructor
複製代碼
在ES5
以前對象的屬性名大多都是字符串,起名字是個難事,並且名字一多動不動重複了就出錯了。並且有的時候咱們拿過別人的代碼,要給其中一個對象增長屬性,咱們也不知道怎麼起名字不重複,這也是ES6
中引入Symbol
的根本緣由。spa
let name = Symbol('name'); //加入 name 做爲描述
let obj = {
[name]: 'Baoyuan' //必須放在方括號之中
};
obj[name]; //'Baoyuan'
複製代碼
對象中的普通屬性,咱們能夠使用Object.keys()
、for...in
或者Object.getOwnPropertyNames()
來進行遍歷,可是他們並不能遍歷出Symbol
類型的屬性名。請注意,它並非私有屬性。咱們能夠使用Object.getOwnPropertySymbols
的方法來獲取指定對象的Symbol
屬性。它會返回當前對象中全部Symbol
類型的屬性的Symbol
值的數組:code
let a = Symbol('a');
let b = Symbol('b');
let c = 'c';
let obj = {
[a]: 'a',
[b]: 'b',
c: 'c'
};
let objNames = Object.getOwnPropertySymbols(obj);
console.log(objNames); // [Symbol(a), Symbol(b)]
let objName = Object.getOwnPropertyNames(obj);
console.log(objName); // ["c"]
複製代碼
使用Reflect.ownKeys
能夠遍歷到全部的屬性名:對象
let names = Reflect.ownKeys(obj);
console.log(names); // ["c", Symbol(a), Symbol(b)]
複製代碼
有時候新建了一個Symbol
值可是在其餘地方咱們但願再次使用,這時即便使用相同的描述符也不會產生同一個值,這時咱們就須要Symbol.for()
:ip
let a = Symbol.for('hello');
let b = Symbol.for('hello');
a === b; // true
複製代碼
其實這兩種寫法都會產生新的Symbol
,不過不一樣的是Symbol
每次都產生一個新的值,而Symbol.for
會先查看給定的key
值是否存在,不存在了再去新建,而且還會被登記在全局環境中供搜索。咱們能夠使用Symbol.keyFor
查看一個已登記的Symbol
值的key
:字符串
Symbol.keyFor(a); // "hello"
複製代碼
咱們先來想一下它的主要特徵
返回一個Symbol
類型,而且是惟一的不會重複。
使用new
操做符初始化會報錯。
能夠接受字符串參數做爲標註,接受對象的時候調用對象的toString
,即便參數相同返回的值也不一樣。
最後查看一下ECMAScript
定義的規範。
When Symbol is called with optional argument description, the following steps are taken:
規範中指出了當咱們調用Symbol
的時候有幾個步驟:
若是咱們使用了new
,就報錯。
若是沒有傳遞參數,那麼就使用undefined
做爲描述字.
若是傳了的話就把它轉換爲字符串。
報錯就返回。
新返回一個惟一的Symbol
值,它的[[Description]]
屬性值爲descString
。