概述
ES5 的對(duì)象屬性名都是字符串姜贡,這容易造成屬性名的沖突冯吓。比如,你使用了一個(gè)他人提供的對(duì)象梗肝,但又想為這個(gè)對(duì)象添加新的方法(mixin 模式),新方法的名字就有可能與現(xiàn)有方法產(chǎn)生沖突铺董。如果有一種機(jī)制巫击,保證每個(gè)屬性的名字都是獨(dú)一無(wú)二的就好了,這樣就從根本上防止屬性名的沖突精续。這就是 ES6 引入Symbol的原因坝锰。
ES6 引入了一種新的原始數(shù)據(jù)類(lèi)型Symbol,表示獨(dú)一無(wú)二的值重付。它是 JavaScript 語(yǔ)言的第七種數(shù)據(jù)類(lèi)型顷级,前六種是:undefined、null确垫、布爾值(Boolean)弓颈、字符串(String)帽芽、數(shù)值(Number)、對(duì)象(Object)翔冀。
注意导街,Symbol函數(shù)前不能使用new命令,否則會(huì)報(bào)錯(cuò)纤子。這是因?yàn)樯傻?Symbol 是一個(gè)原始類(lèi)型的值搬瑰,不是對(duì)象。也就是說(shuō)控硼,由于 Symbol 值不是對(duì)象泽论,所以不能添加屬性】ㄇ基本上翼悴,它是一種類(lèi)似于字符串的數(shù)據(jù)類(lèi)型。
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
上面代碼中幔妨,s1和s2是兩個(gè) Symbol 值抄瓦。如果不加參數(shù),它們?cè)诳刂婆_(tái)的輸出都是Symbol()陶冷,不利于區(qū)分钙姊。有了參數(shù)以后,就等于為它們加上了描述埂伦,輸出的時(shí)候就能夠分清煞额,到底是哪一個(gè)值。
2.作為屬性名的 Symbol
由于每一個(gè) Symbol 值都是不相等的沾谜,這意味著 Symbol 值可以作為標(biāo)識(shí)符膊毁,用于對(duì)象的屬性名,就能保證不會(huì)出現(xiàn)同名的屬性基跑。這對(duì)于一個(gè)對(duì)象由多個(gè)模塊構(gòu)成的情況非常有用婚温,能防止某一個(gè)鍵被不小心改寫(xiě)或覆蓋。
let mySymbol = Symbol();
// 第一種寫(xiě)法
let a = {};
a[mySymbol] = 'Hello!';
// 第二種寫(xiě)法
let a = {
? [mySymbol]: 'Hello!'
};
// 第三種寫(xiě)法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上寫(xiě)法都得到同樣結(jié)果
a[mySymbol] // "Hello!"
上面代碼通過(guò)方括號(hào)結(jié)構(gòu)和Object.defineProperty媳否,將對(duì)象的屬性名指定為一個(gè) Symbol 值栅螟。
注意,Symbol 值作為對(duì)象屬性名時(shí)篱竭,不能用點(diǎn)運(yùn)算符力图。
const mySymbol = Symbol();
const a = {};
a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"
上面代碼中,因?yàn)辄c(diǎn)運(yùn)算符后面總是字符串掺逼,所以不會(huì)讀取mySymbol作為標(biāo)識(shí)名所指代的那個(gè)值吃媒,導(dǎo)致a的屬性名實(shí)際上是一個(gè)字符串,而不是一個(gè) Symbol 值。
實(shí)例:消除魔術(shù)字符串 § ?
魔術(shù)字符串指的是赘那,在代碼之中多次出現(xiàn)刑桑、與代碼形成強(qiáng)耦合的某一個(gè)具體的字符串或者數(shù)值。風(fēng)格良好的代碼募舟,應(yīng)該盡量消除魔術(shù)字符串祠斧,改由含義清晰的變量代替。