天天看點

三.ES6學習 Symbol

概述

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"