概述
ES5中的對象屬性名都是字符串,如果我們使用了一個他人提供的對象,又需要為該對象添加新的方法(mixin模式),新的方法可能會與現有的方法產生沖突,ES6引入了新的數據類型Symbol
來保證每個屬性的名字是獨一無二的。
至此,JavaScript共有七種數據類型:undefined
、null
、布爾值(Boolean)、字符串(String)、數值(Number)、對象(Object)、Symbol
。Symbol的值是通過Symbol
函數生成的,不能使用new
。
let s = Symbol('foo');
typeof s // "symbol"
s1.toString() // "Symbol(foo)"
let s1 = Symbol('foo');
s === s1 // false
作為屬性名的Symbol
let a1 = Symbol.for('abc');
let obj = {
[a1]: '123',
'abc': 345,
'c': 456
};
console.log('obj', obj);
Symbol的值作為對象屬性名時,不能使用點運算符。此時,該屬性是公開屬性,不是私有屬性。
Symbol類型還可以定義一組常量,保證這組常量的值都是不相等的。
const COLOR_RED = Symbol();
const COLOR_GREEN = Symbol();
function getComplement(color) {
switch (color) {
case COLOR_RED:
return COLOR_GREEN;
case COLOR_GREEN:
return COLOR_RED;
default:
throw new Error('Undefined color');
}
}
屬性名的遍歷
Symbol作為屬性名,不會被for...in
、for...of
遍歷,也不會被Object.keys()
、Ojbect.getOwnPropertyNames()
、JSON.stringify()
返回。
它可以通過Object.getOwnPropertySymbols()
遍歷,該方法趕回一個數組,也可以通過Reflect.ownKeys
方法遍歷:
let a1 = Symbol.for('abc');
let obj = {
[a1]: '123',
'abc': 345,
'c': 456
};
console.log('obj', obj);
for (let [key, value] of Object.entries(obj)) {
console.log('let of', key, value);
}
Object.getOwnPropertySymbols(obj).forEach((item) => console.log(obj[item]));
Reflect.ownKeys(obj).forEach((item) => console.log('ownkeys', item, obj[item]));
Symbol.for(), Symbol.keyFor()
通過Symbol.for
方法可以重新使用同一個Symbol值,它的參數是一個字符串,然后搜索是否有以該參數作為名稱的Symbol值。如果有,就返回這個Symbol值,否則會新建并返回一個以該字符串為名稱的Symbol值。
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
Symbol.keyFor
方法返回一個已登記的Symbol類型值的key
。
let s1 = Symbol.for('foo');
Symbol.keyFor(s1) // "foo"
let s2 = Symbol('foo');
Symbol.keyFor(s2) // undefined
內置的Symbol值
ES6提供了11個內置的Symbol值,指向語言內部的使用方法。
Symbol.hasInstance
Symbol.isConcatSpreadable
Symbol.species
Symbol.match
Symbol.replace
Symbol.search
Symbol.split
-
Symbol.iterator
對象進行
for...of
循環時,會調用此方法。 Symbol.toPrimitive
Symbol.toStringTag
Symbol.unscopables
具體使用方法和介紹可以參考阮一峰老師的教程 內置的Symbol值。