溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript的Symbol類型、隱藏屬性及全局注冊表怎么創(chuàng)建

發(fā)布時間:2022-06-02 13:50:22 來源:億速云 閱讀:159 作者:iii 欄目:web開發(fā)

本文小編為大家詳細(xì)介紹“JavaScript的Symbol類型、隱藏屬性及全局注冊表怎么創(chuàng)建”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“JavaScript的Symbol類型、隱藏屬性及全局注冊表怎么創(chuàng)建”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。

JavaScript的Symbol類型、隱藏屬性及全局注冊表怎么創(chuàng)建

Symbol簡介

Symbol類型是JavaScript中的一種特殊的類型,特殊在所有的Symbol類型值都互不相同。我們可以使用“Symbol”來表示唯一的值,下面是創(chuàng)建Symbol對象的案例:

let id = Symbol();

這樣我們就創(chuàng)建了一個Symbol類型的值,并把這個值存儲在了變量id中。

Symbol類型的描述

我們在創(chuàng)建一個Symbol類型變量的時候,可以在參數(shù)中傳入一些秒屬性的字符串,用于描述這個變量的用途信息。
例如:

let id1 = Symbol('狂拽酷炫吊炸天的小明的id');
let id2 = Symbol('低調(diào)奢華有內(nèi)涵的婷婷的id');

Symbol類型在任何時候都是不同的,即使他們擁有相同的描述信息,描述只是一個標(biāo)簽,除此之外就沒有別的用途了,例如:

let id1 = Symbol('id');
let id2 = Symbol('id');
console.log(id1==id2);//false

這個標(biāo)簽存在的意義,個人認(rèn)為和Symbol不能直觀的看到內(nèi)部具體值的特性有關(guān),通過添加一個描述信息,讓我們對變量的用途有更直觀的了解。

Symbol不會隱式轉(zhuǎn)字符串

JavaScript中的大多數(shù)類型都可以直接轉(zhuǎn)換成字符串類型輸出,所以我們不能直觀的看到它的值到底是什么,例如我們可以直接用alert(123)把數(shù)字123轉(zhuǎn)換成字符串彈出。
但是Symbol類型比較特殊,它不能直接轉(zhuǎn)換,例如:

let id = Symbol();
alert(id);//報錯,不能把Symbol類型轉(zhuǎn)為字符串

JavaScript中的Symbol類型不能轉(zhuǎn)成字符串是由于其內(nèi)在的防治語言混亂的“語言保護(hù)”機(jī)制,因為字符串和Symbol在本質(zhì)上有著區(qū)別,不應(yīng)該將其中一個轉(zhuǎn)換成另一個。

試想一下,如果Symbol可以轉(zhuǎn)為字符串,那么它就變成了一個生成獨一無二字符串的函數(shù),就不再具備獨立數(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類似作為對象的屬性鍵

根據(jù)JavaScript的規(guī)范,只有兩種類型的值可以作為對象的屬性鍵:

  1. 字符串

  2. Symbol

如果使用其他類型,則會隱式的轉(zhuǎn)為字符串類型。對象的鍵在前面的章節(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',//注意這里的方括號	
};
console.log(user[id]);

以上兩個案例展示了在對象中插入Symbol類型作為鍵的用法,需要注意的是,在訪問屬性時需要使用obj[id]而不是obj.id,因為obj.id代表的是obj[‘id’]

如果我們使用Symbol作為對象的鍵會有什么效果呢?

for…in中被跳過

Symbol非常明顯的一個特征是,如果對象中使用Symbol作為鍵,那么使用for…in語句是訪問不到Symbol類型的屬性的。

舉個例子:

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]對象的值沒有被打印出來,說明在對象屬性列表中,使用for … in會自動忽略Symbol類型的鍵。

同樣的,Object.keys(user)也會忽略所有的Symbol類型的鍵。

這樣的特性能帶來非常有用的效果,例如我們可以創(chuàng)建只能自己能用的屬性。

雖然我們沒有辦法直接獲取到Symbol鍵,但是Object.assign方法能夠復(fù)制所有的屬性:

let id = Symbol();
let obj = {
    [id] : '123'
}

let obj2 = Object.assign({},obj);
console.log(obj2[id]);

這并不影響Symbol的隱藏屬性,因為復(fù)制后的對象仍然無法獲取Symbol鍵。

隱藏自定義屬性

由于Symbol既不能直接轉(zhuǎn)為字符串,我們沒有辦法直觀的獲得它的值,又不能通過for … in獲得對象的Symbol屬性,也就是說,如果沒有Symbol變量本身,我們就沒有辦法獲得對象內(nèi)部的對應(yīng)屬性。

因此,通過Symbol類型的鍵值,我們可以隱藏屬性,這些屬性只能我們自己訪問,其他人都看不到我們的屬性。

舉個例子:

我們在開發(fā)的過程中,需要和同事“張三”合作,而這個張三創(chuàng)建了一個非常好用的工具ToolTool是一個對象類型,我們想白嫖張三的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]);

以上示例展示了如何在別人寫好的對象上添加自己的屬性,那么為什么要使用Symbol類型而不是常規(guī)的字符串呢?

原因如下:

  1. 對象tool是別人寫好的代碼,原則上我們不應(yīng)該去修改別人的代碼,這樣會造成風(fēng)險;

  2. 避免命名沖突,我們直接使用字符串很有可能會和別人原有的屬性鍵沖突,造成嚴(yán)重的后果;

  3. 使用Symbol永遠(yuǎn)不會發(fā)生命名沖突,因為Symbol都是不同的;

  4. 別人無法訪問Symbol類型的鍵,相當(dāng)于不會和別人的代碼沖突;

錯誤示范:
如果我們不使用Symbol類型,很可能出現(xiàn)以下情況:

let tool = {//張三寫好了的Tool
    usage : "Can do anything",
}

tool.usage = "Boom Boom";
console.log(tool.usage);

以上代碼由于重復(fù)使用”usage”,從而重寫了原屬性,會造成對象原功能異常。

Symbol全局注冊表

所有的Symbol變量都是不同的,即使他們有用相同的標(biāo)簽(描述)。
有些時候,我們希望通過一個字符串名稱(標(biāo)簽),訪問同一個Symbol對象,例如我們在代碼的不同地方訪問相同的Symbol

JavaScript會維護(hù)一個全局的Symbol注冊表,我們可以通過向注冊表中插入Symbol對象,并為對象起一個字符串名稱訪問該對象。

向注冊表插入或者讀取Symbol對象需要使用Symbol.for(key)方法,如果注冊表中有名為key的對象,就返回該對象,否則就插入新對象再返回。

舉個例子:

let id1 = Symbol.for('id');//注冊表內(nèi)沒有名為id的Symbol,創(chuàng)建并返回
let id2 = Symbol.for('id');//注冊表內(nèi)已有名為id的Symbol,直接返回
console.log(id1===id2);//true

我們通過Symbol.for(key)就能以全局變量的方式使用Symbol對象,并使用一個字符串標(biāo)記對象的名字。

相反的,我們還可以使用Symbol.keyFor(Symbol)反向的從對象獲取名稱。

舉個例子:

let id = Symbol.for('id');//注冊表內(nèi)沒有名為id的Symbol,創(chuàng)建并返回
let name = Symbol.keyFor(id);
console.log(name);//id

Symbol.keyFor()函數(shù)只能用在全局Symbol對象上(使用Symbol.for插入的對象),如果用在非全局對象上,就會返回undefined

舉個例子:

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

它們各有用途,我們在后面的會逐步介紹道這些獨特的變量。

總結(jié)

  1. Symbol對象的值是唯一的;

  2. Symbol可以添加一個標(biāo)簽,并通過標(biāo)簽在全局注冊表中查詢對象的實體;

  3. Symbol作為對象的鍵無法被for … in探測到;

  4. 我們可以通過Symbol到全局注冊表訪問全局的Symbol對象;

但是,Symbol并不是完全隱藏的,我們可以通過Object.getOwnPropertySymbols(obj)獲取對象所有的Symbol,或者通過Reflect.ownKeys(obj)獲取對象所有的鍵。

讀到這里,這篇“JavaScript的Symbol類型、隱藏屬性及全局注冊表怎么創(chuàng)建”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI