數(shù)據(jù)類型
????在介紹Symbol之前,我們簡(jiǎn)單介紹一下JavaScript的數(shù)據(jù)類型:
????JavaScript有6中數(shù)據(jù)類型,分別是:
String 字符串類型
Number 數(shù)字類型
Object 對(duì)象類型
Boolean 布爾值類型
Null 空值
Undefined 未定義
????設(shè)計(jì)Symbol的初衷是為了解決對(duì)象屬性名重復(fù)
//定義一個(gè)symbol類型的變量
let sm = Symbol();
console.log(sm);
//打印結(jié)果:Symbol()
console.log(typeof sm);
//打印結(jié)果:symbol
????我們用一個(gè)Symbol( )函數(shù)來(lái)創(chuàng)建一個(gè)symbol類型的變量,我們打印了一下變量sm,得到的結(jié)果是控制臺(tái)輸出:Symbol( ),它代表著一個(gè)獨(dú)一無(wú)二的值,雖然我們看不到它長(zhǎng)什么樣子,但基本上,它有點(diǎn)類似字符串。如何判斷他是獨(dú)一無(wú)二的呢?
let sm1 = Symbol();
let sm2 = Symbol();
sm1 === sm2 //結(jié)果:false
console.log(sm1);//結(jié)果:Symbol()
console.log(sm2);//結(jié)果:Symbol()
????看起來(lái)是一樣的,但是實(shí)際上是不一樣的,如何讓他看起來(lái)不一樣的呢?
let sm1 = Symbol('sm1');
let sm2 = Symbol('sm2');
console.log(sm1);
//結(jié)果:Symbol(sm1)
console.log(sm2);
//結(jié)果:Symbol(sm2)
????用字符串sm1和sm2作為參數(shù),結(jié)果打印出來(lái)的變量sm1和sm2就是Symbol(sm1)和Symbol(sm2),等于加上了描述,很容易區(qū)分出來(lái)。
????需要注意的是,即使參數(shù)一樣,描述一樣,得到的兩個(gè)值也是不相等的:
let sm1 = Symbol('sm');
let sm2 = Symbol('sm');
sm1 === sm2 //結(jié)果:false
????當(dāng)symbol值作為對(duì)象的屬性名的時(shí)候,不能用點(diǎn)運(yùn)算符獲取對(duì)應(yīng)的值。
let name = Symbol();
let person = {
[name]:"張三"
};
console.log(person[name]);
//結(jié)果:張三
console.log(person.name);
//結(jié)果:undefined
//第一種用中括號(hào)的形式[ name ]能正確獲取到,第二種用點(diǎn)運(yùn)算符的形式,獲取失敗。
屬性名的遍歷
????當(dāng)symbol類型的值作為屬性名的時(shí)候,該屬性是不會(huì)出現(xiàn)在for...in和for...of中的,也不會(huì)被Object.keys( )獲取到。
//定義一個(gè)symbol類型的變量name
let name = Symbol();
//定義一個(gè)含有兩種類型屬性的對(duì)象
let person = {
[name]:"張三", //symbol類型
"age":12 //string類型
};
Object.keys(person);//結(jié)果:["age"]
for(let key in person){
console.log(key);
}
//打印結(jié)果:age
//symbol類型和string字符串類型,我們通過(guò)keys( )函數(shù)獲取到的屬性,只有屬性age
getOwnPropertySymbols( )函數(shù) 獲取symbol的key值
????Object.getOwnPropertySymbols( ),它會(huì)找到symbol類型的屬性并且返回一個(gè)數(shù)組,數(shù)組的成員就是symbol類型的屬性值
//定義兩個(gè)symbol類型的變量name,age
let name = Symbol("name");
let age = Symbol("age");
let person = {
[name]:"張三", //symbol類型
[age]:12 //symbol類型
};
Object.getOwnPropertySymbols(person);
//結(jié)果:[Symbol(name), Symbol(age)]
Reflect.ownKeys( )函數(shù)
????獲取所有類型的屬性,不管它是字符串類型還是symbol類型
//定義一個(gè)對(duì)象,含有兩種類型的屬性
let person = {
[Symbol('name')]:"張三",
"age": 21
};
Reflect.ownKeys(person);
//結(jié)果:["age",Symbol(name)]
Symbol.for( )函數(shù)
????根據(jù)參數(shù)名,去全局環(huán)境中搜索是否有以該參數(shù)為名的symbol值,有就返回它,沒(méi)有就以該參數(shù)名來(lái)創(chuàng)建一個(gè)新的symbol值。
let n1 = Symbol.for('name');
let n2 = Symbol.for('name');
console.log(n1 === n2);
//結(jié)果:true
????Symbol.for( )創(chuàng)建的symbol值會(huì)被登記在全局環(huán)境中,供以后用Symbol.for( )來(lái)搜索,而Symbol( )創(chuàng)建的變量就沒(méi)有這樣的效果了。
let n1 = Symbol('name');
let n2 = Symbol.for('name');
console.log(n1 === n2);
//結(jié)果:false
????第一行我們用Symbol( )來(lái)創(chuàng)建的一個(gè)symbol值,按照上述的所說(shuō)的,它不會(huì)被登記在全局環(huán)境中;所以,第二行我們用Symbol.for( )去找的時(shí)候,是找不到的,找不到怎么辦?此時(shí)Symbol.for( )會(huì)自動(dòng)創(chuàng)建一個(gè)新的symbol值,也就是說(shuō)n1,n2是不同的兩個(gè)symbol值了,所以進(jìn)行全相等比較的時(shí)候,會(huì)返回:false。
Symbol.keyFor( )函數(shù)
????返回一個(gè)以被登記在全局環(huán)境中的symbol值的key,沒(méi)有就返回undefined。注意這句話的一個(gè)關(guān)鍵詞:“被登記在全局環(huán)境中”,也就是說(shuō)這個(gè)symbol值是被Symbol.for( )創(chuàng)建的,不是被Symbol( )創(chuàng)建的。
let n1 = Symbol.for('name');
Symbol.KeyFor(n1);
//結(jié)果:name
????上面的變量n1是被Symbol.for( )創(chuàng)建,不是被Symbol( )創(chuàng)建的,所以用Symbol.keyFor( )去找,是能找到的,會(huì)返回這個(gè)symbol值的key,也就是它的描述:name。
let n1 = Symbol('name');
Symbol.KeyFor(n1);
//結(jié)果:undefined
//1、Symbol( )創(chuàng)建symbol值不會(huì)被登記在全局環(huán)境中供Symbol.for( )和Symbol.keyFor( )搜索;
//2、Symbol.keyFor( )函數(shù)在全局環(huán)境中找不到對(duì)應(yīng)的symbol,就回返回undefined。