首頁  >  文章  >  web前端  >  JavaScript的Symbol類型、隱藏屬性及全域登錄詳解

JavaScript的Symbol類型、隱藏屬性及全域登錄詳解

WBOY
WBOY轉載
2022-06-02 11:50:342807瀏覽

本篇文章為大家帶來了關於javascript的相關知識,其中主要介紹了關於Symbol類型、隱藏屬性及全局註冊表的相關問題,包括了Symbol類型的描述、Symbol不會隱式轉字符串等問題,下面一起來看一下,希望對大家有幫助。

JavaScript的Symbol類型、隱藏屬性及全域登錄詳解

【相關推薦:javascript影片教學web前端

##Symbol簡介

Symbol類型是JavaScript中的一種特殊的類型,特殊在所有的Symbol類型值都互不相同。我們可以使用「Symbol」來表示唯一的值,以下是創建Symbol物件的案例:

let id = Symbol();
這樣我們就創建了一個

Symbol類型的值,並且把這個值儲存在變數id#了變數中。

Symbol類型的描述

我們在創建一個

Symbol類型變數的時候,可以在參數中傳入一些秒屬性的字串,用來描述這個變數的用途資訊。 例如:

let id1 = Symbol('狂拽酷炫吊炸天的小明的id');
let id2 = Symbol('低调奢华有内涵的婷婷的id');

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

let id1 = Symbol('id');
let id2 = Symbol('id');
console.log(id1==id2);//false
這個標籤存在的意義,個人認為和

Symbol不能直觀的看到內部具體值的特性有關,通過添加一個描述信息,讓我們對變量的用途有更直觀的了解。

Symbol不會隱式轉字串

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

let id = Symbol();
alert(id);//报错,不能把Symbol类型转为字符串

JavaScript中的Symbol類型不能轉換成字符串是由於其內在的防治語言混亂的「語言保護」機制,因為字串和Symbol在本質上有著區別,不應該將其中一個轉換成另一個。

試想一下,如果

Symbol可以轉為字串,那麼它就變成了一個產生獨一無二字串的函數,就不再具備獨立資料類型的必要。

如果我們真的想知道

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類似作為物件的屬性鍵

根據

JavaScript的規範,只有兩種類型的值可以作為物件的屬性鍵:

    字串
  1. Symbol
如果使用其他類型,則會隱式的轉為字串類型。物件的鍵在前面的章節有詳細的介紹,這裡不再重複。

建立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]);
執行上述程式碼,得到以下結果:

> xiaoming
可以發現,

[id]物件的值沒有被列印出來,說明在物件屬性清單中,使用for … in會自動忽略Symbol類型的鍵。

同樣的,

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

這樣的特性能帶來非常有用的效果,例如我們可以創造出只能自己能使用的屬性。

雖然我們沒有辦法直接取得到

Symbol鍵,但Object.assign方法能夠複製所有的屬性:

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

let obj2 = Object.assign({},obj);
console.log(obj2[id]);
這並不影響

Symbol的隱藏屬性,因為複製後的物件仍然無法取得Symbol鍵。

隐藏自定义属性

由于Symbol既不能直接转为字符串,我们没有办法直观的获得它的值,又不能通过for … in获得对象的Symbol属性,也就是说,如果没有Symbol变量本身,我们就没有办法获得对象内部的对应属性。

因此,通过Symbol类型的键值,我们可以隐藏属性,这些属性只能我们自己访问,其他人都看不到我们的属性。

举个例子:

我们在开发的过程中,需要和同事“张三”合作,而这个张三创建了一个非常好用的工具ToolTool是一个对象类型,我们想白嫖张三的Tool,并在此基础上添加一些自己的属性。

我们就可以通过添加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类型而不是常规的字符串呢?

原因如下:

  1. 对象tool是别人写好的代码,原则上我们不应该去修改别人的代码,这样会造成风险;
  2. 避免命名冲突,我们直接使用字符串很有可能会和别人原有的属性键冲突,造成严重的后果;
  3. 使用Symbol永远不会发生命名冲突,因为Symbol都是不同的;
  4. 别人无法访问Symbol类型的键,相当于不会和别人的代码冲突;

错误示范:
如果我们不使用Symbol类型,很可能出现以下情况:

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

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

以上代码由于重复使用”usage”,从而重写了原属性,会造成对象原功能异常。

Symbol全局注册表

所有的Symbol变量都是不同的,即使他们有用相同的标签(描述)。
有些时候,我们希望通过一个字符串名称(标签),访问同一个Symbol对象,例如我们在代码的不同地方访问相同的Symbol

JavaScript会维护一个全局的Symbol注册表,我们可以通过向注册表中插入Symbol对象,并为对象起一个字符串名称访问该对象。

向注册表插入或者读取Symbol对象需要使用Symbol.for(key)方法,如果注册表中有名为key的对象,就返回该对象,否则就插入新对象再返回。

举个例子:

let id1 = Symbol.for('id');//注册表内没有名为id的Symbol,创建并返回
let id2 = Symbol.for('id');//注册表内已有名为id的Symbol,直接返回
console.log(id1===id2);//true

我们通过Symbol.for(key)就能以全局变量的方式使用Symbol对象,并使用一个字符串标记对象的名字。

相反的,我们还可以使用Symbol.keyFor(Symbol)反向的从对象获取名称。

举个例子:

let id = Symbol.for('id');//注册表内没有名为id的Symbol,创建并返回
let name = Symbol.keyFor(id);
console.log(name);//id

Symbol.keyFor()函数只能用在全局Symbol对象上(使用Symbol.for插入的对象),如果用在非全局对象上,就会返回undefined

举个例子:

let id = Symbol('id');//局部Symbol
let name = Symbol.keyFor(id);
console.log(name);//undefined

系统Symbol

JavaScript有许多系统Symbol,例如:

  • Symbol.hasInstance
  • Symbol.iterator
  • Symbol.toPrimitive

它们各有用途,我们在后面的会逐步介绍道这些独特的变量。

总结

  1. Symbol对象的值是唯一的;
  2. Symbol可以添加一个标签,并通过标签在全局注册表中查询对象的实体;
  3. Symbol作为对象的键无法被for … in探测到;
  4. 我们可以通过Symbol到全局注册表访问全局的Symbol对象;

但是,Symbol并不是完全隐藏的,我们可以通过Object.getOwnPropertySymbols(obj)获取对象所有的Symbol,或者通过Reflect.ownKeys(obj)获取对象所有的键。

【相关推荐:javascript视频教程web前端

以上是JavaScript的Symbol類型、隱藏屬性及全域登錄詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除