【面試題】JS第七種數(shù)據(jù)類(lèi)型Symbol詳解

JS第七種數(shù)據(jù)類(lèi)型Symbol詳解

點(diǎn)擊打開(kāi)視頻講解更加詳細(xì)

一、什么是Symbol?

Symbol是ES6中引入的一種新的基本數(shù)據(jù)類(lèi)型,用于表示一個(gè)獨(dú)一無(wú)二的值。它是JavaScript中的第
七種數(shù)據(jù)類(lèi)型,與undefined、null、Number(數(shù)值)、String(字符串)、Boolean(布爾值)、
Object(對(duì)象)并列。

Symbol特點(diǎn):

  • Symbol的值是唯一的,用來(lái)解決命名沖突問(wèn)題
  • Symbol值不能與其他數(shù)據(jù)進(jìn)行運(yùn)算
  • Symbol定義的對(duì)象屬性不能使用for...in循環(huán)遍歷,但是可以使用Reflect.ownKeys來(lái)獲取對(duì)象的所有鍵名

基本用法:

let a = Symbol("末晨曦吖");
console.log(a); // Symbol(末晨曦吖)
console.log(typeof a); //symbol

// 相同參數(shù) Symbol() 返回的值不相等
let b = Symbol("末晨曦吖");
console.log(a === b); //false

為什么相同參數(shù) Symbol() 返回的值不相等???

因?yàn)槭褂肧ymbol()創(chuàng)建一個(gè)Symbol類(lèi)型的值并賦值給a變量后,你就得到了一個(gè)在內(nèi)存中獨(dú)一無(wú)二的值。現(xiàn)在除了通過(guò)變量a,任何人在任何作用域內(nèi)都無(wú)法重新創(chuàng)建出這個(gè)值。所以就算我們通過(guò)相同參數(shù)創(chuàng)建的b,結(jié)果還是不相等的。

盡管a和b都是使用Symbol()創(chuàng)建出來(lái)的,但是它們?cè)趦?nèi)存中看起來(lái)卻是這樣的:

11111111111111111.png

實(shí)際上,a變量拿到了內(nèi)存中某塊內(nèi)存的唯一引用(這里所說(shuō)的引用,其實(shí)就是該內(nèi)存的地址)。如果不借助a變量,你不可能再得到這個(gè)地址。因此:

a !== b;  //a和b持有的是兩塊內(nèi)存的引用
 
const c = a;  //手動(dòng)把a(bǔ)里保存的地址保存在c變量中
a === c;  //c和a現(xiàn)在指向同一塊內(nèi)存,因?yàn)樗鼈儽4媪送瑯拥牡刂?
222222222222222.png

這種行為看似難以理解,但其實(shí)它與對(duì)象遵循相同的規(guī)則,如:

let a = {};
let b = {};
 
a !== b;  //a和b各自被分配了不同的內(nèi)存,因此它們保存了不同的地址
 
//借助變量a,變量c拿到了a指向的那個(gè)對(duì)象的地址,因此兩者相等
let c = a;
a === c;

但是對(duì)于同為基本數(shù)據(jù)類(lèi)型的字符串來(lái)說(shuō),它不遵循類(lèi)似的規(guī)則。比如:

let a = "123";
let b = "123";
 
a === b;  //返回true。兩者在常量區(qū)引用同一個(gè)字符串
3333333333333.png

我們首先通過(guò)變量a在內(nèi)存中創(chuàng)建了字符串“123”,然后在不借助變量a的情況下,又通過(guò)var b = "123"拿到了對(duì)“123”這個(gè)字符串的引用,兩者指向內(nèi)存中的同一塊內(nèi)存地址。

因此我們說(shuō),a無(wú)法確保別的變量無(wú)法拿到它保存的地址(前提是不通過(guò)a)。但是對(duì)于var a = Symbol()這樣的語(yǔ)句,a變量?jī)?nèi)保存的值是唯一的,因?yàn)槌私柚鷄變量,你永遠(yuǎn)無(wú)法得到a中保存的值。這也是Symbol的本質(zhì)。

作為屬性名的Symbol

let mySymbol = Symbol();
// 第一種寫(xiě)法
let a = {};
a[mySymbol] = 'Hello!';
// 第二種寫(xiě)法
let a = {
  [mySymbol]: 'Hello!'
};
// 第三種寫(xiě)法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上寫(xiě)法都得到同樣結(jié)果
a[mySymbol] // "Hello!"
注意,Symbol值作為對(duì)象屬性名時(shí),不能用點(diǎn)運(yùn)算符。

let a = {};
let name = Symbol();
a.name = 'lili';
a[name] = 'lucy';
console.log(a.name,a[name]);//lili,lucy
Symbol值作為屬性名時(shí),該屬性還是公開(kāi)屬性,不是私有屬性。

二、Symbol中的方法

1、Symbol.for()

我們知道Symbo()創(chuàng)建的兩個(gè)變量永遠(yuǎn)不會(huì)是相同的。那么如果我們需要重新使用同一個(gè)Symbol怎么辦,總不能需要挨個(gè)去進(jìn)行比較吧。還好,es6為我們提供了Symbol.for()方法。

參數(shù)是symbol類(lèi)型的描述信息,不同于Symbol(),這個(gè)而參數(shù)只能是字符串或者是undefined,若已經(jīng)創(chuàng)建了則返回這個(gè)symbol,否則就進(jìn)行創(chuàng)建并將這個(gè)新的symbol返回,代碼如下

let name = Symbol.for("末晨曦");
let name1 = Symbol.for("末晨曦");
console.log(name === name1);  // true

請(qǐng)注意,我們?cè)谑褂脛?chuàng)建描述信息為"末晨曦"的變量的時(shí)候,使用的是for,而不是Symbol(),倘若使用Symbol()進(jìn)行首次創(chuàng)建,for會(huì)再次創(chuàng)建一次,二者不會(huì)相等,代碼如下:

let name = Symbol("末晨曦");
let name1 = Symbol.for("末晨曦");
console.log(name === name1);  // false

原因在于Symbol.for()會(huì)有一個(gè)登記機(jī)制,使用for只會(huì)對(duì)通過(guò)for創(chuàng)建的symbol進(jìn)行檢查,不會(huì)對(duì)Symbol()創(chuàng)建的進(jìn)行檢查。

2、Symbol.keyFor()

這個(gè)方法參數(shù)是一個(gè)通過(guò)Symbol.for()創(chuàng)建的symbol類(lèi)型變量,返回這個(gè)symbol變量的描述信息。

let name = Symbol.for("末晨曦");
console.log(Symbol.keyFor(name)); // "末晨曦"
let name1 = Symbol("末晨曦");
console.log(Symbol.keyFor(name1)); // undefined 不能查找Symbol()創(chuàng)建的變量

若對(duì)您有幫助,請(qǐng)點(diǎn)擊跳轉(zhuǎn)B站一鍵三連哦!感謝支持?。?!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容