詳解JavaScript的Symbol類型、隱藏屬性、全局注冊(cè)表
Symbol類型的使用
在前文《JavaScript的8種數(shù)據(jù)類型》中,我們已經(jīng)簡單的介紹過了JavaScript
的Symbol
類型,下面對(duì)其使用方法和使用場(chǎng)景做一個(gè)簡單的介紹。
Symbol簡介
Symbol
類型是JavaScript
中的一種特殊的類型,特殊在所有的Symbol
類型值都互不相同。我們可以使用“Symbol”來表示唯一的值,下面是創(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)簽,除此之外就沒有別的用途了,例如:
let id1 = Symbol('id'); let id2 = Symbol('id'); console.log(id1==id2);//false
這個(gè)標(biāo)簽存在的意義,個(gè)人認(rèn)為和Symbol
不能直觀的看到內(nèi)部具體值的特性有關(guān),通過添加一個(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)在的防治語言混亂的“語言保護(hù)”機(jī)制,因?yàn)樽址?code>Symbol在本質(zhì)上有著區(qū)別,不應(yīng)該將其中一個(gè)轉(zhuǎn)換成另一個(gè)。
試想一下,如果Symbol
可以轉(zhuǎn)為字符串,那么它就變成了一個(gè)生成獨(dú)一無二字符串的函數(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
類型作為鍵的用法,需要注意的是,在訪問屬性時(shí)需要使用obj[id]
而不是obj.id
,因?yàn)?code>obj.id代表的是obj[‘id’]
。
如果我們使用Symbol
作為對(duì)象的鍵會(huì)有什么效果呢?
for…in中被跳過
Symbol
非常明顯的一個(gè)特征是,如果對(duì)象中使用Symbol
作為鍵,那么使用for…in
語句是訪問不到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ì)象的值沒有被打印出來,說明在對(duì)象屬性列表中,使用for … in
會(huì)自動(dòng)忽略Symbol
類型的鍵。
同樣的,Object.keys(user)
也會(huì)忽略所有的Symbol
類型的鍵。
這樣的特性能帶來非常有用的效果,例如我們可以創(chuàng)建只能自己能用的屬性。
雖然我們沒有辦法直接獲取到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ì)象仍然無法獲取Symbol
鍵。
隱藏自定義屬性
由于Symbol
既不能直接轉(zhuǎn)為字符串,我們沒有辦法直觀的獲得它的值,又不能通過for … in
獲得對(duì)象的Symbol
屬性,也就是說,如果沒有Symbol
變量本身,我們就沒有辦法獲得對(duì)象內(nèi)部的對(duì)應(yīng)屬性。
因此,通過Symbol
類型的鍵值,我們可以隱藏屬性,這些屬性只能我們自己訪問,其他人都看不到我們的屬性。
舉個(gè)例子:
我們?cè)陂_發(fā)的過程中,需要和同事“張三”合作,而這個(gè)張三創(chuàng)建了一個(gè)非常好用的工具Tool
,Tool
是一個(gè)對(duì)象類型,我們想白嫖張三的Tool
,并在此基礎(chǔ)上添加一些自己的屬性。
我們就可以通過添加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都是不同的; - 別人無法訪問
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í)候,我們希望通過一個(gè)字符串名稱(標(biāo)簽),訪問同一個(gè)Symbol
對(duì)象,例如我們?cè)诖a的不同地方訪問相同的Symbol
。
JavaScript
會(huì)維護(hù)一個(gè)全局的Symbol
注冊(cè)表,我們可以通過向注冊(cè)表中插入Symbol
對(duì)象,并為對(duì)象起一個(gè)字符串名稱訪問該對(duì)象。
向注冊(cè)表插入或者讀取Symbol
對(duì)象需要使用Symbol.for(key)
方法,如果注冊(cè)表中有名為key
的對(duì)象,就返回該對(duì)象,否則就插入新對(duì)象再返回。
舉個(gè)例子:
let id1 = Symbol.for('id');//注冊(cè)表內(nèi)沒有名為id的Symbol,創(chuàng)建并返回 let id2 = Symbol.for('id');//注冊(cè)表內(nèi)已有名為id的Symbol,直接返回 console.log(id1===id2);//true
我們通過Symbol.for(key)
就能以全局變量的方式使用Symbol
對(duì)象,并使用一個(gè)字符串標(biāo)記對(duì)象的名字。
相反的,我們還可以使用Symbol.keyFor(Symbol)
反向的從對(duì)象獲取名稱。
舉個(gè)例子:
let id = Symbol.for('id');//注冊(cè)表內(nèi)沒有名為id的Symbol,創(chuàng)建并返回 let name = Symbol.keyFor(id); console.log(name);//id
Symbol.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.hasInstance
Symbol.iterator
Symbol.toPrimitive
它們各有用途,我們?cè)诤竺娴臅?huì)逐步介紹道這些獨(dú)特的變量。
總結(jié)
Symbol
對(duì)象的值是唯一的;Symbol
可以添加一個(gè)標(biāo)簽,并通過標(biāo)簽在全局注冊(cè)表中查詢對(duì)象的實(shí)體;Symbol
作為對(duì)象的鍵無法被for … in
探測(cè)到;- 我們可以通過
Symbol
到全局注冊(cè)表訪問全局的Symbol
對(duì)象;
但是,Symbol
并不是完全隱藏的,我們可以通過Object.getOwnPropertySymbols(obj)
獲取對(duì)象所有的Symbol
,或者通過Reflect.ownKeys(obj)
獲取對(duì)象所有的鍵。
到此這篇關(guān)于JavaScript的Symbol類型、隱藏屬性、全局注冊(cè)表的文章就介紹到這了,更多相關(guān)js Symbol類型、隱藏屬性、全局注冊(cè)表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript設(shè)計(jì)模式之工廠模式和構(gòu)造器模式
這篇文章主要介紹了JavaScript設(shè)計(jì)模式之工廠模式和構(gòu)造器模式,本文同時(shí)講解了設(shè)計(jì)模式的類別如創(chuàng)建型設(shè)計(jì)模式、結(jié)構(gòu)型設(shè)計(jì)模式、行為設(shè)計(jì)模式等內(nèi)容,需要的朋友可以參考下2015-02-02關(guān)聯(lián)的Select,可以支持客戶端動(dòng)態(tài)更新
關(guān)聯(lián)的Select,可以支持客戶端動(dòng)態(tài)更新...2006-09-09javascript檢查某個(gè)元素在數(shù)組中的索引值
在js中提供數(shù)據(jù)查找了函數(shù)有很多,但我查找了很久都沒有能實(shí)現(xiàn)我要的方法,后來發(fā)現(xiàn)可以使用indexOf函數(shù)來實(shí)現(xiàn)查找與定位數(shù)組元素索引值的具體方法,各位朋友可參考2016-03-03javascript刪除一個(gè)html元素節(jié)點(diǎn)的方法
這篇文章主要介紹了javascript刪除一個(gè)html元素節(jié)點(diǎn)的方法,可通過獲取父節(jié)點(diǎn)再查找并刪除子節(jié)點(diǎn)來實(shí)現(xiàn)該功能,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-12-12動(dòng)態(tài)的創(chuàng)建一個(gè)元素createElement及刪除一個(gè)元素
本文用示例為大家介紹下動(dòng)態(tài)創(chuàng)建一個(gè)元素createElement及刪除一個(gè)元素,感興趣的朋友可以參考下2014-01-01js自動(dòng)查找select下拉的菜單并選擇(示例代碼)
這篇文章主要介紹了js自動(dòng)查找select下拉的菜單并選擇(示例代碼)需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-02-02echarts tooltip自適應(yīng)寬高讓提示框適應(yīng)不同屏幕尺寸demo
這篇文章主要為大家介紹了echarts tooltip自適應(yīng)寬高讓提示框適應(yīng)不同屏幕尺寸,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10- 當(dāng)處理JavaScript字符串時(shí),有許多有趣的技巧可以提高你的編碼效率,這篇文章將介紹一些有關(guān)JavaScript字符串的技巧,讓你在字符串操作方面更加?jì)故?/div> 2023-10-10
最新評(píng)論