參考:ECMAScript 6 入門
Symbol
為什么要引入Symbol:
ES5 的對(duì)象屬性名都是字符串,這容易造成屬性名的沖突。比如,你使用了一個(gè)他人提供的對(duì)象,但又想為這個(gè)對(duì)象添加新的方法(mixin 模式),新方法的名字就有可能與現(xiàn)有方法產(chǎn)生沖突。如果有一種機(jī)制,保證每個(gè)屬性的名字都是獨(dú)一無(wú)二的就好了,這樣就從根本上防止屬性名的沖突。這就是 ES6 引入Symbol的原因。
是什么?
它是 JavaScript 語(yǔ)言的第七種數(shù)據(jù)類型,表示獨(dú)一無(wú)二的值,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數(shù)值(Number)、對(duì)象(Object)。
生成Symbol類型的值:
重點(diǎn):不能用new命令生成symbol類型的值
原因:因?yàn)樯傻?Symbol 是一個(gè)原始類型的值,不是對(duì)象。(可以認(rèn)為通過(guò)調(diào)用Symbol()方法返回一個(gè)symbol類型的值?通過(guò)new生成的都是對(duì)象。)
無(wú)參數(shù)形式:
let s = Symbol();
typeof s // "symbol"
有參數(shù)形式:
let s1 = Symbol('foo');
兩種形式的比較:(關(guān)鍵詞:描述)
本質(zhì)是一樣的;但有參數(shù)形式的參數(shù)是一種描述,方便debug;也可以將對(duì)象傳入作為參數(shù),這個(gè)對(duì)象也是對(duì)symbol值的描述。
非重點(diǎn)區(qū):
Symbol 值不能與其他類型的值進(jìn)行運(yùn)算,會(huì)報(bào)錯(cuò)。
let sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
Symbol 值可以顯式轉(zhuǎn)為字符串(本質(zhì)是因?yàn)檎{(diào)用了傳入的參數(shù)的toString方法)
let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
Symbol 值也可以轉(zhuǎn)為布爾值
let sym = Symbol();
Boolean(sym) // true
!sym // false
作為屬性名舉例:
let mySymbol = Symbol();
// 第一種寫法
let a = {};
a[mySymbol] = 'Hello!';
// 第二種寫法
let a = {
[mySymbol]: 'Hello!'
};
不能通過(guò)點(diǎn)的方式訪問(wèn)symbol屬性的值。因?yàn)橥ㄟ^(guò)點(diǎn)形式訪問(wèn)的,那個(gè)屬性名必須是字符串,這也解釋了為什么在上面那個(gè)例子中,定義symbol屬性時(shí)必須加上[]。
const mySymbol = Symbol();
const a = {};
a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"
哪種場(chǎng)景下用Symbol最合適?
我們只作為一個(gè)flag使用的時(shí)候,變量值取任何字符串都不影響結(jié)果的時(shí)候。
如何遍歷symbol屬性:
Symbol 作為屬性名,不能被任何方式遍歷或枚舉,除了使用Object.getOwnPropertySymbols
方法(其實(shí)還可以通過(guò)Reflect.ownKeys
這種方式獲取,此處不表)
非重點(diǎn)區(qū):
Symbol.for() 與 Symbol() 的區(qū)別:
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
講解:當(dāng)給s1賦值時(shí),這個(gè)symbol的值會(huì)在全局環(huán)境中登記(通過(guò)foo: Symbol('foo')
的形式登記),再通過(guò)Symbol.for('foo')
,會(huì)根據(jù)foo去全局搜索,如果找到了,就返回原來(lái)的symbol值(感覺(jué)有點(diǎn)像java中字符串的定義:String a = 'symbol'; String b = 'symbol'; System.out.print(a === b); // true
)
Symbol()
每次都會(huì)返回新的(Symbol.for() 與 Symbol() 的區(qū)別,感覺(jué)有點(diǎn)類似于java中String a = 'symbol'; String b = new String('symbol');
的區(qū)別,不過(guò)Symbol()的值不是對(duì)象)
ES6內(nèi)置symbol屬性名舉例:
Symbol.hasInstance
Symbol.isConcatSpreadable
Symbol.species
Symbol.match
Symbol.replace
Symbol.search
Symbol.split
Symbol.iterator
Symbol.toPrimitive
Symbol.toStringTag