符號

Browser Support

  • Chrome: 38.
  • Edge: 12.
  • Firefox: 36.
  • Safari: 9.

Source

符號原始值代表不會與任何其他值 (包括其他符號原始值的值) 衝突的唯一值。由相同字元組成的兩個字串原始值會評估為完全相等:

String() === String()
> true

String( "My string." ) === String( "My string." );
> true

不過,使用 Symbol() 函式建立的兩個符號絕對不會完全相等:

Symbol() === Symbol()
> false

此特徵可讓您使用符號做為物件中的專屬屬性鍵,避免與其他程式碼可能新增至該物件的鍵發生衝突。

const mySymbol = Symbol( "Desc" );

const myObject = {};
myObject[mySymbol] = "propSymbol";

myObject
> Object { Symbol("Desc"): "propSymbol" }

符號分為三種類型:

  • 使用 Symbol() 建立的符號
  • 使用 Symbol.for() 從全域符號註冊機制中設定及擷取的共用符號
  • 「已知符號」是 Symbol 物件上定義為靜態屬性的項目。這些符號包含不會意外覆寫的內部方法。

Symbol() 會接受說明 (或「符號名稱」) 做為選用引數。這些說明是供偵錯用的易讀標籤,不會影響結果的唯一性。任何對 Symbol 的呼叫都會傳回完全獨特的符號原始元素,即使多個呼叫的說明相同也一樣:

Symbol( "My symbol." ) === Symbol( "My symbol." );
> false

與其他基本資料類型一樣,符號會從原型繼承方法和屬性。舉例來說,您可以將說明做為已建立符號的繼承屬性存取:

let mySymbol = Symbol( "My symbol." );

mySymbol.description
> "My symbol."

但您無法使用 new 關鍵字建立符號:

let mySymbol = new Symbol();

> Uncaught TypeError: Symbol is not a constructor

符號無法列舉,也就是說,使用標準方法對符號進行疊代時,系統無法使用符號屬性。getOwnPropertySymbols() 方法可存取物件的符號屬性。

共用符號

Symbol.for() 方法會嘗試使用指定字串做為索引鍵,在執行階段全域符號登錄檔中查詢任何現有的符號,並在找到相符的符號時傳回該符號。如果找不到,就會使用指定的鍵建立符號,並將其新增至全域註冊表:

let sharedSymbol = Symbol.for( "My key." );

sharedSymbol === Symbol.for( "My key." )
> true

這些鍵與作者建立的 Symbol 基本元素指派的說明並無功能重疊。如要存取符號註冊表中的符號,您必須先使用 for() 建立符號:

Symbol( "String" ) === Symbol( "String" );
> false

Symbol( "String" ) === Symbol.for( "String" );
> false

Symbol.for( "String" ) === Symbol.for( "String" );
> true

如要從符號登錄表中擷取任何符號的索引鍵,請使用 Symbol.keyFor()

let mySymbol = Symbol.for( "Key." );

Symbol.keyFor( mySymbol ) ;
> "Key."

「已知」符號

已知符號Symbol 物件的靜態屬性,每個符號本身都是符號。已知符號提供專屬的屬性鍵,可用於存取及修改 JavaScript 內建方法,同時避免核心行為遭到意外覆寫。

Symbol;
> function Symbol()
    asyncIterator: Symbol(Symbol.asyncIterator)
    for: function for()
    hasInstance: Symbol("Symbol.hasInstance")
    isConcatSpreadable: Symbol("Symbol.isConcatSpreadable")
    iterator: Symbol(Symbol.iterator)
    keyFor: function keyFor()
    length: 0
    match: Symbol("Symbol.match")
    matchAll: Symbol("Symbol.matchAll")
    name: "Symbol"
    prototype: Object {  }
    replace: Symbol("Symbol.replace")
    search: Symbol("Symbol.search")
    species: Symbol("Symbol.species")
    split: Symbol("Symbol.split")
    toPrimitive: Symbol("Symbol.toPrimitive")
    toStringTag: Symbol("Symbol.toStringTag")
    unscopables: Symbol("Symbol.unscopables")
    <prototype>: function ()

由於符號是 ES6 專屬的功能,因此這些符號值可用於開發人員修改 JavaScript 行為時,做為「擴充點」使用,而不會引發向後相容性的問題。

常見的符號值通常會加上 @@ 前置字串或包在 % 中,以便將鍵與可變動的原型區分開來。舉例來說,@@match (或 %match%) 是不可變動的 Symbol.match 參照,而非 String.prototype.match

進行隨堂測驗

您可以使用 new 建立符號嗎?

下列哪一個敘述可用來描述「well-known」符號?

`Symbol` 物件的靜態屬性
常用的符號
用於存取及修改 JavaScript 內建方法的專屬屬性鍵