ES6 中的 Symbol

JavaScript 之 Symbol

Symbol是什麼

SymbolES6中新引入的一種基本數據類型。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
複製代碼

Symbol的使用姿式

給對象增長屬性

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值可是在其餘地方咱們但願再次使用,這時即便使用相同的描述符也不會產生同一個值,這時咱們就須要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"
複製代碼

ECMAScript 中的定義

咱們先來想一下它的主要特徵

  • 返回一個Symbol類型,而且是惟一的不會重複。

  • 使用new操做符初始化會報錯。

  • 能夠接受字符串參數做爲標註,接受對象的時候調用對象的toString,即便參數相同返回的值也不一樣。

最後查看一下ECMAScript定義的規範

When Symbol is called with optional argument description, the following steps are taken:

  1. If NewTarget is not undefined, throw a TypeError exception.
  2. If description is undefined, let descString be undefined.
  3. Else, let descString be ToString(description).
  4. ReturnIfAbrupt(descString).
  5. Return a new unique Symbol value whose [[Description]] value is descString.

規範中指出了當咱們調用Symbol的時候有幾個步驟:

  1. 若是咱們使用了new,就報錯。

  2. 若是沒有傳遞參數,那麼就使用undefined做爲描述字.

  3. 若是傳了的話就把它轉換爲字符串。

  4. 報錯就返回。

  5. 新返回一個惟一的Symbol值,它的[[Description]]屬性值爲descString

相關文章
相關標籤/搜索