Symbol
何為Symbol
ES5中對(duì)象的屬性名都是字符串,容易造成屬性名的沖突。也就是說,當(dāng)我們?cè)谡{(diào)用別人的對(duì)象的同時(shí),又想為這個(gè)對(duì)象添加一個(gè)新的方法,這個(gè)新的方法名字就容易與原對(duì)象中已有的方法名沖突。ES6引入Symbol,就是為了解決這樣的問題。
Symbol是ES6新添加的一個(gè)基本數(shù)據(jù)類型。所以在ES6中一共有七種數(shù)據(jù)類型:undefined、null、Bollean、String、Number、Object以及Symbol.
創(chuàng)建Symbol
Symbol值通過Symbol函數(shù)生成。注意,Symbol前面不能使用new 運(yùn)算符,否則會(huì)報(bào)錯(cuò)。這是因?yàn)镾ymbol是一種原始數(shù)據(jù)類型,不是對(duì)象
let s = Symbol();
typeof s;   // "symbol"
Symbol函數(shù)可以接受字符串作為參數(shù),這主要便于在控制顯示,或者轉(zhuǎn)為字符串時(shí),方便區(qū)分。如:
var s1 = Symbol('foo');
var s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
注意: Symbol的參數(shù)僅用于對(duì)當(dāng)前Symbol值的描述,并無其他實(shí)際意義。相同參數(shù)Symbol函數(shù)的返回值是不一樣的。
var s1 = Symbol();
var s2 = Symbol();
s1 === s2;      // false
var s1 = Symbol('foo');
var s2 = Symbol('foo');
s1 === s2;      // false
Symbol值不可與其他類型的值進(jìn)行運(yùn)算。
var sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string
但是,Symbol值可以顯示為字符串。
var sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
作為屬性名的Symbol
Symbol值作為對(duì)象的屬性名,有以下三種寫法:
var mySymbol = Symbol();
// 第一種寫法
var a = {};
a[mySymbol] = 'Hello!';
// 第二種寫法  在對(duì)象內(nèi)部使用Symbol值定義屬性,Symbol值必須放在方括號(hào)中。
var a = {
    [mySymbol]: 'Hello!'
};
// 第三種學(xué)法
var a = {};
Object.defineProperty(a, mySymbol, {value: 'Hello!'});
注意:Symbol值作為對(duì)象屬性名時(shí),不能用點(diǎn)運(yùn)算符。因?yàn)辄c(diǎn)運(yùn)算符后面總是字符串。
屬性名的遍歷 Object.getOwnPropertySymbols()
Object.getOwnPropertySymbols 返回的是一個(gè)數(shù)組,數(shù)組成員是作為當(dāng)前對(duì)象的屬性名的Symbol值。
var obj = {};
var a = Symbol('a');
var b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
var objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols);     // [Symbol(a), Symbol(b)]
注意:Symbol 作為屬性名,該屬性不會(huì)出現(xiàn)在for...in、for...of循環(huán)中,也不會(huì)被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
Reflact.ownKeys()可以返回所有類型的鍵名,包括常規(guī)鍵名和Symbol鍵名。
let obj = {
  [Symbol('my_key')]: 1,
  enum: 2,
  nonEnum: 3
};
Reflect.ownKeys(obj)
//  ["enum", "nonEnum", Symbol(my_key)]
Symbol.for() Symbol.keyFor()
有時(shí),我們希望重新使用同一個(gè)Symbol值,Symbol.for方法可以做到這一點(diǎn)。它接受一個(gè)字符串作為參數(shù),然后搜索有沒有以該參數(shù)作為名稱的Symbol值。如果有,就返回這個(gè)Symbol值,否則就新建并返回一個(gè)以該字符串為名稱的Symbol值。
Symbol.for()和Symbol()都會(huì)生成新的Symbol.他們的區(qū)別是,Symbol.for()創(chuàng)建的Symbol是全局的,而Symbol()創(chuàng)建的是某個(gè)對(duì)象的Symbol值。Symbol.for()不會(huì)每次調(diào)用就返回一個(gè)新的Symbol類型的值,而是會(huì)先檢查給定的key是否已經(jīng)存在,如果不存在才會(huì)新建一個(gè)值。比如,如果你調(diào)用Symbol.for("cat")30次,每次都會(huì)返回同一個(gè)Symbol值,但是調(diào)用Symbol("cat")30次,會(huì)返回30個(gè)不同的Symbol值。
Symbol.for("bar") === Symbol.for("bar")
// true
Symbol("bar") === Symbol("bar")
// false
Symbol.keyFor()返回Symbol.for()創(chuàng)建的Symbol值得key.
var s1 = Symbol.for('foo');
Symbol.keyFor(s1);  // 'foo'
var s2 = Symbol('foo');
Symbol.keyFor(s2);  // undefined
                            總結(jié)
                            
                        - 上一篇: 过滤器 拦截器 区别
 - 下一篇: Java日期处理 开始时间-结束时间查询