一、Symbol 簡介
Symbol
是 JavaScript 中的一種基本數據類型,它表示唯一的標識符。Symbol
的主要目的是防止屬性名沖突,尤其是在多個代碼庫或模塊中共享對象時。Symbol
值可以用作對象的屬性名,這樣可以確保屬性名是唯一的,不會與其他屬性名沖突。Symbol定義的對象屬性不能使用for…in循環遍歷,但可以使用 Reflect.ownKeys
來獲取對象的所有鍵名。
二、Symbol 的創建
可以使用 Symbol()
函數來創建一個新的 Symbol
值。這個函數可以接受一個可選的字符串參數,作為 Symbol
的描述。描述只是為了調試目的,不會影響 Symbol
的唯一性。
let s1 = Symbol();
console.log(s1, typeof s1); // Symbol() "symbol"let s2 = Symbol('尚硅谷');
let s2_2= Symbol('尚硅谷');
console.log(s2 === s2_2); // false// 使用 Symbol.for 定義
let s3 = Symbol.for('尚硅谷');
let s3_2 = Symbol.for('尚硅谷');
console.log(s3 === s3_2); // true
在上面的代碼中,s1
、s2
和 s2_2
都是不同的 Symbol
值,盡管 s2
和 s2_2
的描述相同。
三、Symbol 的應用
1. 作為對象的屬性名
Symbol
可以用作對象的屬性名,這樣可以確保屬性名是唯一的,不會與其他屬性名沖突。
let game = {name:'俄羅斯方塊',up: function(){},down: function(){}
};let methods = {up: Symbol(),down: Symbol()
};game[methods.up] = function(){console.log("我可以改變形狀");
}game[methods.down] = function(){console.log("我可以快速下降!!");
}console.log(game);
在上面的代碼中,methods.up
和 methods.down
是兩個 Symbol
值,它們被用作 game
對象的屬性名。這樣,即使其他代碼也使用了 up
和 down
作為屬性名,它們也不會沖突。
2. Symbol 內置屬性
除了定義自己使用的 Symbol 值以外,ES6 還提供了 11 個內置的 Symbol 值,指向語言內部使用的方法,稱為“魔術方法”,因為它們會在特定的場景下自動執行。。例如,Symbol.hasInstance
可以用來定義一個對象是否是某個類的實例,Symbol.isConcatSpreadable
可以用來控制數組的展開行為。
- Symbol.hasInstance:當其他對象使用
instanceof
運算符,判斷是否為該對象的實例時,會調用這個方法。 - Symbol.isConcatSpreadable:對象的
Symbol.isConcatSpreadable
屬性等于的是一個布爾值,表示該對象用于Array.prototype.concat()
時,是否可以展開。 - Symbol.species:創建衍生對象時,會使用該屬性。
- Symbol.match:當執行
str.match(myObject)
時,如果該屬性存在,會調用它,返回該方法的返回值。 - Symbol.replace:當該對象被
str.replace(myObject)
方法調用時,會返回該方法的返回值。 - Symbol.search:當該對象被
str.search(myObject)
方法調用時,會返回該方法的返回值。 - Symbol.split:當該對象被
str.split(myObject)
方法調用時,會返回該方法的返回值。 - Symbol.iterator:對象進行
for...of
循環時,會調用Symbol.iterator
方法,返回該對象的默認遍歷器。 - Symbol.toPrimitive:該對象被轉為原始類型的值時,會調用這個方法,返回該對象對應的原始類型值。
- Symbol.toStringTag:在該對象上面調用
toString
方法時,返回該方法的返回值。 - Symbol.unscopables:該對象指定了使用
with
關鍵字時,哪些屬性會被with
環境排除。
class Person{static [Symbol.hasInstance](param){console.log(param);console.log("我被用來檢測類型了");return false;}
}let o = {};console.log(o instanceof Person);const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));
在上面的代碼中,Symbol.hasInstance
被用來定義 Person
類的 instanceof
操作符的行為,Symbol.isConcatSpreadable
被用來控制數組的 concat
方法的展開行為。
四、總結
Symbol
是 JavaScript 中一種非常有用的數據類型,它可以用來創建唯一的標識符,防止屬性名沖突,并且可以用來定義對象的一些特殊行為。通過合理使用 Symbol
,可以使代碼更加健壯和可維護。