概述
ES6引入了一種新的原始資料類型Symbol,表示獨一無二的值,最多的用法是用來定義對象的唯一屬性名。
ES6資料類型除了Number、String、Boolean、Object、null和undefined,還新增了Symbol。
基本用法
Symbol函數棧不能用new指令,因為Symbol是原始資料類型,不是對象。可以接受一個字元串作為參數,為建立的Symbol描述,用來顯示在控制台或者作為字元串的時候使用,便于區分。
let sy = Symbol("KK");
console.log(sy); // Symbol(KK)
typeof(sy); // "symbol"
// 相同參數 Symbol() 傳回的值不相等
let sy1 = Symbol("kk");
sy === sy1; // false
使用場景
作為屬性名
由于每一個Symbol的值都是不相等的,是以Symbol作為對象的屬性名,可以保證屬性不重名。
let sy = Symbol("key1");
// 寫法1
let syObject = {};
syObject[sy] = "kk";
console.log(syObject); // {Symbol(key1): "kk"}
// 寫法2
let syObject = {
[sy]: "kk"
};
console.log(syObject); // {Symbol(key1): "kk"}
// 寫法3
let syObject = {};
Object.defineProperty(syObject, sy, {value: "kk"});
console.log(syObject); // {Symbol(key1): "kk"}
Symbol作為對象屬性名時不能用".“運算符,要用方括号。因為”."運算符後面是字元串,是以取到的是字元串sy屬性,而不是Symbol值sy屬性。
let syObject = {};
syObject[sy] = "kk";
syObject[sy]; // "kk"
syObject.sy; // undefined
注意點
Symbol值作為屬性名時,該屬性是公有屬性而不是私有屬性,可以在類的外部通路。但是不會出現在for…in、for…of的循環中,也不會被Object.keys()、Object.getOwnPropertyNames()傳回。如果讀取到一個對象的Symbol屬性,可以通過 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。
let syObject = {};
syObject[sy] = "kk";
console.log(syObject);
for (let i in syObject) {
console.log(i);
} // 無輸出
Object.keys(syObject); // []
Object.getOwnPropertySymbols(syObject); // [Symbol(key1)]
Reflect.ownKeys(syObject); // [Symbol(key1)]
定義常量
使用Symbol定義常量可以保證一組常量的值都不相等:
const COLOR_RED = Symbol("red");
const COLOR_YELLOW = Symbol("yellow");
const COLOR_BLUE = Symbol("blue");
function ColorException(message) {
this.message = message;
this.name = "ColorException";
}
function getConstantName(color) {
switch (color) {
case COLOR_RED :
return "COLOR_RED";
case COLOR_YELLOW :
return "COLOR_YELLOW ";
case COLOR_BLUE:
return "COLOR_BLUE";
default:
throw new ColorException("Can't find this color");
}
}
try {
var color = "green"; // green 引發異常
var colorName = getConstantName(color);
} catch (e) {
var colorName = "unknown";
console.log(e.message, e.name); // 傳遞異常對象到錯誤處理
}
Symbol的值是唯一的,是以不會出現相同值的常量,可以保證switch按照代碼預想的方式執行。
Symbol.for()
Symbol.for()類似單例模式,首先會在全局搜尋被登記的Symbol中是否有該字元串參數作為名稱的Symbol值,如果有即傳回該Symbol值,若沒有則建立并傳回一個以該字元串參數為名稱的Symbol值,并登記在全局環境中供搜尋。
let yellow = Symbol("Yellow");
let yellow1 = Symbol.for("Yellow");
yellow === yellow1; // false
let yellow2 = Symbol.for("Yellow");
yellow1 === yellow2; // true
Symbol.keyFor()
Symbol.keyFor()傳回一個已登記的Symbol類型值的key,用來檢測該字元串參數作為名稱的Symbol值是否已被登記。
let yellow1 = Symbol.for("Yellow");
Symbol.keyFor(yellow1); // "Yellow"