天天看點

JS-學習ES6之-Symbol資料類型目錄1.為什麼要有Symbol2. Symbol可以傳參數3. Symbol 作為屬性名的用法4. Symbol.for()

目錄

  • 概述
  • Symbol可以傳參數
  • Symbol 作為屬性名的用法
  • Symbol.for()

1.為什麼要有Symbol

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

Symbol

的原因。

ES6 引入了一種新的原始資料類型

Symbol

,表示獨一無二的值。它是 JavaScript 語言的第七種資料類型,前六種是:

undefined

null

、布爾值(Boolean)、字元串(String)、數值(Number)、對象(Object)。

Symbol 值通過

Symbol

函數生成。這就是說,對象的屬性名現在可以有兩種類型,一種是原來就有的字元串,另一種就是新增的 Symbol 類型。凡是屬性名屬于 Symbol 類型,就都是獨一無二的,可以保證不會與其他屬性名産生沖突。

注意,Symbol函數前不能使用new指令,否則會報錯。這是因為生成的 Symbol 是一個原始類型的值,不是對象。也就是說,由于 Symbol 值不是對象,是以不能添加屬性。基本上,它是一種類似于字元串的資料類型。

let s = Symbol();
           

2. Symbol可以傳參數

Symbol

函數可以接受一個字元串作為參數,表示對

Symbol

執行個體的描述,主要是為了在控制台顯示,或者轉為字元串時,比較容易區分。

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
           

上面代碼中,

s1

s2

是兩個

Symbol

值。如果不加參數,它們在控制台的輸出都是

Symbol()

,不利于區分。有了參數以後,就等于為它們加上了描述,輸出的時候就能夠厘清,到底是哪一個值。

注意,

Symbol

函數的參數隻是表示對目前

Symbol

值的描述,是以相同參數的

Symbol

函數的傳回值是不相等的。

// 沒有參數
let s1 = Symbol();
let s2 = Symbol();

s1 === s2; //false

// 有參數的情況
let s3 = Symbol('foo');
let s4 = Symbol('foo');

s3 === s4; // false
           

3. Symbol 作為屬性名的用法

由于每一個

Symbol

值都是不相等的,這意味着

Symbol

值可以作為辨別符,用于對象的屬性名,就能保證不會出現同名的屬性。這對于一個對象由多個子產品構成的情況非常有用,能防止某一個鍵被不小心改寫或覆寫。

let s = Symbol();
// 第一種寫法
let a = {
    [s]: 'hello'
}
// 第二種寫法
let a = {};
a[s] = 'hello';
// 第三種寫法
let a = {};
Object.defineProperty(a, s, {value: 'hello'});

// 以上寫法都會得到相同的結果
a[s] = 'hello';
           

注意,

Symbol

值作為對象屬性名時,不能用點運算符,隻能用中括号([])。

a.s = 'hello'; // 會将 s 當做字元串來處理,而不是 Symbol 資料格式

a[s]; // undefined
           

注意:

Symbol

作為屬性名,該屬性不會出現在

for...in

for...of

循環中,也不會被

Object.keys()

Object.getOwnPropertyNames()

JSON.stringify()

傳回。

但是,它也不是私有屬性,有一個

Object.getOwnPropertySymbols

方法,可以擷取指定對象的所有

Symbol

屬性名。

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)]
           

4. Symbol.for()

有時,我們希望重新使用同一個

Symbol

值,

Symbol.for

方法可以做到這一點。它接受一個字元串作為參數,然後搜尋有沒有以該參數作為名稱的

Symbol

值。如果有,就傳回這個

Symbol

值,否則就建立并傳回一個以該字元串為名稱的

Symbol

值。

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');

s1 === s2; // true

// 注意對比 Symbol()
let s3 = Symbol('bar');
let s4 = Symbol('bar');

s3 === s4; // false
           

繼續閱讀