詳解JavaScript的Symbol類型、隱藏屬性、全局注冊(cè)表
Symbol類型的使用
在前文《JavaScript的8種數(shù)據(jù)類型》中,我們已經(jīng)簡(jiǎn)單的介紹過(guò)了JavaScript的Symbol類型,下面對(duì)其使用方法和使用場(chǎng)景做一個(gè)簡(jiǎn)單的介紹。
Symbol簡(jiǎn)介
Symbol類型是JavaScript中的一種特殊的類型,特殊在所有的Symbol類型值都互不相同。我們可以使用“Symbol”來(lái)表示唯一的值,下面是創(chuàng)建Symbol對(duì)象的案例:
let id = Symbol();
這樣我們就創(chuàng)建了一個(gè)Symbol類型的值,并把這個(gè)值存儲(chǔ)在了變量id中。
Symbol類型的描述
我們?cè)趧?chuàng)建一個(gè)Symbol類型變量的時(shí)候,可以在參數(shù)中傳入一些秒屬性的字符串,用于描述這個(gè)變量的用途信息。
例如:
let id1 = Symbol('狂拽酷炫吊炸天的小明的id');
let id2 = Symbol('低調(diào)奢華有內(nèi)涵的婷婷的id');Symbol類型在任何時(shí)候都是不同的,即使他們擁有相同的描述信息,描述只是一個(gè)標(biāo)簽,除此之外就沒(méi)有別的用途了,例如:
let id1 = Symbol('id');
let id2 = Symbol('id');
console.log(id1==id2);//false這個(gè)標(biāo)簽存在的意義,個(gè)人認(rèn)為和Symbol不能直觀的看到內(nèi)部具體值的特性有關(guān),通過(guò)添加一個(gè)描述信息,讓我們對(duì)變量的用途有更直觀的了解。
Symbol不會(huì)隱式轉(zhuǎn)字符串
JavaScript中的大多數(shù)類型都可以直接轉(zhuǎn)換成字符串類型輸出,所以我們不能直觀的看到它的值到底是什么,例如我們可以直接用alert(123)把數(shù)字123轉(zhuǎn)換成字符串彈出。
但是Symbol類型比較特殊,它不能直接轉(zhuǎn)換,例如:
let id = Symbol(); alert(id);//報(bào)錯(cuò),不能把Symbol類型轉(zhuǎn)為字符串
JavaScript中的Symbol類型不能轉(zhuǎn)成字符串是由于其內(nèi)在的防治語(yǔ)言混亂的“語(yǔ)言保護(hù)”機(jī)制,因?yàn)樽址?code>Symbol在本質(zhì)上有著區(qū)別,不應(yīng)該將其中一個(gè)轉(zhuǎn)換成另一個(gè)。
試想一下,如果Symbol可以轉(zhuǎn)為字符串,那么它就變成了一個(gè)生成獨(dú)一無(wú)二字符串的函數(shù),就不再具備獨(dú)立數(shù)據(jù)類型的必要。
如果我們真的想知道Symbol變量的值,我們可以使用.toString()方法,如下所示:
let id = Symbol('this is identification');
console.log(id.toString());//Symbol(this is identification);或者使用.description屬性,獲取描述信息:
let id = Symbol('加油,奧利給');
console.log(id.description);//加油,奧利給”Symbol類似作為對(duì)象的屬性鍵
根據(jù)JavaScript的規(guī)范,只有兩種類型的值可以作為對(duì)象的屬性鍵:
- 字符串
- Symbol
如果使用其他類型,則會(huì)隱式的轉(zhuǎn)為字符串類型。對(duì)象的鍵在前面的章節(jié)有詳細(xì)的介紹,這里不再重復(fù)。
創(chuàng)建Symbol鍵
將Symbol作為鍵值有兩種方法:
例1:
let id = Symbol('id');
let user = {};
user[id] = 'id value';//添加Symbol鍵
console.log(user[id]);//id value例2:
let id = Symbol('id');
let user = {
[id]:'id value',//注意這里的方括號(hào)
};
console.log(user[id]);以上兩個(gè)案例展示了在對(duì)象中插入Symbol類型作為鍵的用法,需要注意的是,在訪問(wèn)屬性時(shí)需要使用obj[id]而不是obj.id,因?yàn)?code>obj.id代表的是obj[‘id’]。
如果我們使用Symbol作為對(duì)象的鍵會(huì)有什么效果呢?
for…in中被跳過(guò)
Symbol非常明顯的一個(gè)特征是,如果對(duì)象中使用Symbol作為鍵,那么使用for…in語(yǔ)句是訪問(wèn)不到Symbol類型的屬性的。
舉個(gè)例子:
let id = Symbol('id');
let user = {
name : 'xiaoming',
[id] : 'id',
};
for (let key in user) console.log(user[key]);執(zhí)行以上代碼,得到以下結(jié)果:
> xiaoming
可以發(fā)現(xiàn),[id]對(duì)象的值沒(méi)有被打印出來(lái),說(shuō)明在對(duì)象屬性列表中,使用for … in會(huì)自動(dòng)忽略Symbol類型的鍵。
同樣的,Object.keys(user)也會(huì)忽略所有的Symbol類型的鍵。
這樣的特性能帶來(lái)非常有用的效果,例如我們可以創(chuàng)建只能自己能用的屬性。
雖然我們沒(méi)有辦法直接獲取到Symbol鍵,但是Object.assign方法能夠復(fù)制所有的屬性:
let id = Symbol();
let obj = {
[id] : '123'
}
let obj2 = Object.assign({},obj);
console.log(obj2[id]);這并不影響Symbol的隱藏屬性,因?yàn)閺?fù)制后的對(duì)象仍然無(wú)法獲取Symbol鍵。
隱藏自定義屬性
由于Symbol既不能直接轉(zhuǎn)為字符串,我們沒(méi)有辦法直觀的獲得它的值,又不能通過(guò)for … in獲得對(duì)象的Symbol屬性,也就是說(shuō),如果沒(méi)有Symbol變量本身,我們就沒(méi)有辦法獲得對(duì)象內(nèi)部的對(duì)應(yīng)屬性。
因此,通過(guò)Symbol類型的鍵值,我們可以隱藏屬性,這些屬性只能我們自己訪問(wèn),其他人都看不到我們的屬性。
舉個(gè)例子:
我們?cè)陂_發(fā)的過(guò)程中,需要和同事“張三”合作,而這個(gè)張三創(chuàng)建了一個(gè)非常好用的工具Tool,Tool是一個(gè)對(duì)象類型,我們想白嫖張三的Tool,并在此基礎(chǔ)上添加一些自己的屬性。
我們就可以通過(guò)添加Symbol類型的鍵:
let tool = {//張三寫好了的Tool
usage : "Can do anything",
}
let name = Symbol("My tool obj");
tool[name] = "This is my tool";
console.log(tool[name]);以上示例展示了如何在別人寫好的對(duì)象上添加自己的屬性,那么為什么要使用Symbol類型而不是常規(guī)的字符串呢?
原因如下:
- 對(duì)象
tool是別人寫好的代碼,原則上我們不應(yīng)該去修改別人的代碼,這樣會(huì)造成風(fēng)險(xiǎn); - 避免命名沖突,我們直接使用字符串很有可能會(huì)和別人原有的屬性鍵沖突,造成嚴(yán)重的后果;使用
Symbol永遠(yuǎn)不會(huì)發(fā)生命名沖突,因?yàn)?code>Symbol都是不同的; - 別人無(wú)法訪問(wèn)
Symbol類型的鍵,相當(dāng)于不會(huì)和別人的代碼沖突;
錯(cuò)誤示范:
如果我們不使用Symbol類型,很可能出現(xiàn)以下情況:
let tool = {//張三寫好了的Tool
usage : "Can do anything",
}
tool.usage = "Boom Boom";
console.log(tool.usage);以上代碼由于重復(fù)使用”usage”,從而重寫了原屬性,會(huì)造成對(duì)象原功能異常。
Symbol全局注冊(cè)表
所有的Symbol變量都是不同的,即使他們有用相同的標(biāo)簽(描述)。
有些時(shí)候,我們希望通過(guò)一個(gè)字符串名稱(標(biāo)簽),訪問(wèn)同一個(gè)Symbol對(duì)象,例如我們?cè)诖a的不同地方訪問(wèn)相同的Symbol。
JavaScript會(huì)維護(hù)一個(gè)全局的Symbol注冊(cè)表,我們可以通過(guò)向注冊(cè)表中插入Symbol對(duì)象,并為對(duì)象起一個(gè)字符串名稱訪問(wèn)該對(duì)象。
向注冊(cè)表插入或者讀取Symbol對(duì)象需要使用Symbol.for(key)方法,如果注冊(cè)表中有名為key的對(duì)象,就返回該對(duì)象,否則就插入新對(duì)象再返回。
舉個(gè)例子:
let id1 = Symbol.for('id');//注冊(cè)表內(nèi)沒(méi)有名為id的Symbol,創(chuàng)建并返回
let id2 = Symbol.for('id');//注冊(cè)表內(nèi)已有名為id的Symbol,直接返回
console.log(id1===id2);//true我們通過(guò)Symbol.for(key)就能以全局變量的方式使用Symbol對(duì)象,并使用一個(gè)字符串標(biāo)記對(duì)象的名字。
相反的,我們還可以使用Symbol.keyFor(Symbol)反向的從對(duì)象獲取名稱。
舉個(gè)例子:
let id = Symbol.for('id');//注冊(cè)表內(nèi)沒(méi)有名為id的Symbol,創(chuàng)建并返回
let name = Symbol.keyFor(id);
console.log(name);//idSymbol.keyFor()函數(shù)只能用在全局Symbol對(duì)象上(使用Symbol.for插入的對(duì)象),如果用在非全局對(duì)象上,就會(huì)返回undefined。
舉個(gè)例子:
let id = Symbol('id');//局部Symbol
let name = Symbol.keyFor(id);
console.log(name);//undefined系統(tǒng)Symbol
JavaScript有許多系統(tǒng)Symbol,例如:
Symbol.hasInstanceSymbol.iteratorSymbol.toPrimitive
它們各有用途,我們?cè)诤竺娴臅?huì)逐步介紹道這些獨(dú)特的變量。
總結(jié)
Symbol對(duì)象的值是唯一的;Symbol可以添加一個(gè)標(biāo)簽,并通過(guò)標(biāo)簽在全局注冊(cè)表中查詢對(duì)象的實(shí)體;Symbol作為對(duì)象的鍵無(wú)法被for … in探測(cè)到;- 我們可以通過(guò)
Symbol到全局注冊(cè)表訪問(wèn)全局的Symbol對(duì)象;
但是,Symbol并不是完全隱藏的,我們可以通過(guò)Object.getOwnPropertySymbols(obj)獲取對(duì)象所有的Symbol,或者通過(guò)Reflect.ownKeys(obj)獲取對(duì)象所有的鍵。
到此這篇關(guān)于JavaScript的Symbol類型、隱藏屬性、全局注冊(cè)表的文章就介紹到這了,更多相關(guān)js Symbol類型、隱藏屬性、全局注冊(cè)表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uniapp頁(yè)面跳轉(zhuǎn)的五種方式總結(jié)
這篇文章主要給大家介紹了關(guān)于uniapp頁(yè)面跳轉(zhuǎn)的五種方式,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-03-03
js實(shí)現(xiàn)增加數(shù)字顯示的環(huán)形進(jìn)度條效果
本文主要分享了js實(shí)現(xiàn)增加數(shù)字顯示的環(huán)形進(jìn)度條效果的示例代碼。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02
JS中數(shù)學(xué)計(jì)算精度問(wèn)題的解決方案
這篇文章主要給大家介紹了JS中數(shù)學(xué)計(jì)算精度問(wèn)題的解決方案,文中通過(guò)代碼示例和圖文結(jié)合給大家講解非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12
JavaScript利用正則表達(dá)式去除日期中的“-”
第一種,將日期字符串先截取,然后拼接;第二種,就是利用正則表達(dá)式去掉“-”本例選擇第二種,比較快捷不容易出錯(cuò)2014-07-07
javascript實(shí)現(xiàn)div浮動(dòng)在網(wǎng)頁(yè)最頂上并帶關(guān)閉按鈕效果實(shí)例
我們有時(shí)會(huì)看到有些網(wǎng)站最頂部一直會(huì)跟著我們滾動(dòng)而滾動(dòng)了,這種方法其實(shí)很簡(jiǎn)單,下面我來(lái)給大推薦一個(gè)javascript實(shí)現(xiàn)div浮動(dòng)在網(wǎng)頁(yè)最頂上并帶關(guān)閉按鈕效果2013-08-08

