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