最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

你知道JavaScript Symbol類型怎么用嗎

 更新時間:2020年01月08日 10:27:03   作者:技術(shù)漫談  
這篇文章主要介紹了你知道JavaScript Symbol類型怎么用嗎,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Symbol 類型

根據(jù)規(guī)范,對象的屬性鍵只能是字符串類型或者 Symbol 類型。不是 Number,也不是 Boolean,只有字符串或 Symbol 這兩種類型。

到目前為止,我們只見過字符串?,F(xiàn)在我們來看看 Symbol 能給我們帶來什么好處。

Symbol

"Symbol" 值表示唯一的標(biāo)識符。

可以使用 Symbol() 來創(chuàng)建這種類型的值:

// id 是 symbol 的一個實例化對象
let id = Symbol();

創(chuàng)建時,我們可以給 Symbol 一個描述(也稱為 Symbol 名),這在代碼調(diào)試時非常有用:

// id 是描述為 "id" 的 Symbol
let id = Symbol("id");

Symbol 保證是唯一的。即使我們創(chuàng)建了許多具有相同描述的 Symbol,它們的值也是不同。描述只是一個標(biāo)簽,不影響任何東西。

例如,這里有兩個描述相同的 Symbol —— 它們不相等:

let id1 = Symbol("id");
let id2 = Symbol("id");

alert(id1 == id2); // false

如果你熟悉 Ruby 或者其他有 "Symbol" 的語言 —— 別被誤導(dǎo)。JavaScript 的 Symbol 是不同的。

注意:Symbol 不會被自動轉(zhuǎn)換為字符串

JavaScript 中的大多數(shù)值都支持字符串的隱式轉(zhuǎn)換。例如,我們可以 alert 任何值,都可以生效。Symbol 比較特殊,它不會被自動轉(zhuǎn)換。

例如,這個 alert 將會提示出錯:

let id = Symbol("id");
alert(id); // 類型錯誤:無法將 Symbol 值轉(zhuǎn)換為字符串。

這是一種防止混亂的“語言保護(hù)”,因為字符串和 Symbol 有本質(zhì)上的不同,不應(yīng)該意外地將它們轉(zhuǎn)換成另一個。

如果我們真的想顯示一個 Symbol,我們需要在它上面調(diào)用 .toString(),如下所示:

let id = Symbol("id");
alert(id.toString()); // Symbol(id),現(xiàn)在它有效了

或者獲取 symbol.description 屬性,只顯示描述(description):

let id = Symbol("id");
alert(id.description); // id

“隱藏”屬性

Symbol 允許我們創(chuàng)建對象的“隱藏”屬性,代碼的任何其他部分都不能意外訪問或重寫這些屬性。

例如,如果我們使用的是屬于第三方代碼的 user 對象,我們想要給它們添加一些標(biāo)識符。

我們可以給它們使用 Symbol 鍵:

let user = { // 屬于另一個代碼
 name: "John"
};

let id = Symbol("id");

user[id] = 1;

alert( user[id] ); // 我們可以使用 Symbol 作為鍵來訪問數(shù)據(jù)

在字符串 "id" 上使用 Symbol("id") 有什么好處?

因為 user 屬于另一個代碼,另一個代碼也使用它執(zhí)行一些操作,所以我們不應(yīng)該在它上面加任何字段,這樣很不安全。但是 Symbol 不會被意外訪問到,所以第三方代碼看不到它,所以使用 Symbol 也許不會有什么問題。
另外,假設(shè)另一個腳本希望在 user 中有自己的標(biāo)識符,以實現(xiàn)自己的目的。這可能是另一個 JavaScript 庫,因此腳本之間完全不了解彼此。

然后該腳本可以創(chuàng)建自己的 Symbol("id"),像這樣:

// ...
let id = Symbol("id");

user[id] = "Their id value";

我們的標(biāo)識符和他們的標(biāo)識符之間不會有沖突,因為 Symbol 總是不同的,即使它們有相同的名字。

……但如果我們處于同樣的目的,使用字符串 "id" 而不是用 symbol,那么 就會 出現(xiàn)沖突:

let user = { name: "John" };

// 我們的腳本使用了 "id" 屬性。
user.id = "Our id value";

// ……另一個腳本也想將 "id" 用于它的目的……  

user.id = "Their id value"
// 砰!無意中被另一個腳本重寫了 id!

字面量中的 Symbol

如果我們要在對象字面量 {...} 中使用 Symbol,則需要使用方括號把它括起來。

就像這樣:

let id = Symbol("id");

let user = {
 name: "John",
 [id]: 123 // 而不是 "id:123"
};

這是因為我們需要變量 id 的值作為鍵,而不是字符串 "id"。

Symbol 在 for..in 中會被跳過

Symbolic 屬性不參與 for..in 循環(huán)。

例如:

let id = Symbol("id");
let user = {
 name: "John",
 age: 30,
 [id]: 123
};

for (let key in user) alert(key); // name, age (no symbols)

// 使用 Symbol 任務(wù)直接訪問
alert( "Direct: " + user[id] );

Object.keys(user) 也會忽略它們。這是一般“隱藏符號屬性”原則的一部分。如果另一個腳本或庫遍歷我們的對象,它不會意外地訪問到符號屬性。

相反,Object.assign 會同時復(fù)制字符串和 symbol 屬性:

let id = Symbol("id");
let user = {
 [id]: 123
};

let clone = Object.assign({}, user);

alert( clone[id] ); // 123

這里并不矛盾,就是這樣設(shè)計的。這里的想法是當(dāng)我們克隆或者合并一個 object 時,通常希望 所有 屬性被復(fù)制(包括像 id 這樣的 Symbol)。

其他類型的屬性鍵被強(qiáng)制為字符串:

我們只能在對象中使用字符串或 symbol 作為鍵,其它類型會被轉(zhuǎn)換為字符串。

例如,在作為屬性鍵使用時,數(shù)字 0 變成了字符串 "0":

let obj = {
 0: "test" // 和 "0": "test" 一樣
};

// 兩個 alert 都訪問相同的屬性(Number 0 被轉(zhuǎn)換為字符串 "0")
alert( obj["0"] ); // test
alert( obj[0] ); // test(同一個屬性)

全局 symbol

正如我們所看到的,通常所有的 Symbol 都是不同的,即使它們有相同的名字。但有時我們想要名字相同的 Symbol 具有相同的實體。例如,應(yīng)用程序的不同部分想要訪問的 Symbol "id" 指的是完全相同的屬性。

為了實現(xiàn)這一點,這里有一個 全局 Symbol 注冊表。我們可以在其中創(chuàng)建 Symbol 并在稍后訪問它們,它可以確保每次訪問相同名字的 Symbol 時,返回的都是相同的 Symbol。

要從注冊表中讀?。ú淮嬖趧t創(chuàng)建)Symbol,請使用 Symbol.for(key)。

該調(diào)用會檢查全局注冊表,如果有一個描述為 key 的 Symbol,則返回該 Symbol,否則將創(chuàng)建一個新 Symbol(Symbol(key)),并通過給定的 key 將其存儲在注冊表中。

例如:

// 從全局注冊表中讀取
let id = Symbol.for("id"); // 如果該 Symbol 不存在,則創(chuàng)建它

// 再次讀?。赡苁窃诖a中的另一個位置)
let idAgain = Symbol.for("id");

// 相同的 Symbol
alert( id === idAgain ); // true

注冊表內(nèi)的 Symbol 被稱為 全局 Symbol。如果我們想要一個應(yīng)用程序范圍內(nèi)的 Symbol,可以在代碼中隨處訪問 —— 這就是它們的用途。

這聽起來像 Ruby:

在一些編程語言中,例如 Ruby,每個名字都有一個 Symbol。

正如我們所看到的,在 JavaScript 中,全局 Symbol 也是這樣的。

Symbol.keyFor

對于全局 Symbol,不僅有 Symbol.for(key) 按名字返回一個 Symbol,還有一個反向調(diào)用:Symbol.keyFor(sym),它的作用完全反過來:通過全局 Symbol 返回一個名字。

例如:

// 通過 name 獲取 Symbol
let sym = Symbol.for("name");
let sym2 = Symbol.for("id");

// 通過 Symbol 獲取 name
alert( Symbol.keyFor(sym) ); // name
alert( Symbol.keyFor(sym2) ); // id

Symbol.keyFor 內(nèi)部使用全局 Symbol 注冊表來查找 Symbol 的鍵。所以它不適用于非全局 Symbol。如果 Symbol 不是全局的,它將無法找到它并返回 undefined。

也就是說,任何 Symbol 都具有 description 屬性。

例如:

let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");

alert( Symbol.keyFor(globalSymbol) ); // name,全局 Symbol
alert( Symbol.keyFor(localSymbol) ); // undefined,非全局

alert( localSymbol.description ); // name

系統(tǒng) Symbol

JavaScript 內(nèi)部有很多“系統(tǒng)” Symbol,我們可以使用它們來微調(diào)對象的各個方面。
它們都被列在了眾所周知的 Symbol 表的規(guī)范中:

  • Symbol.hasInstance
  • Symbol.isConcatSpreadable
  • Symbol.iterator
  • Symbol.toPrimitive
  • ……等等。

例如,Symbol.toPrimitive 允許我們將對象描述為原始值轉(zhuǎn)換。我們很快就會看到它的使用。
當(dāng)我們研究相應(yīng)的語言特征時,我們對其他的 Symbol 也會慢慢熟悉起來。

總結(jié)

Symbol 是唯一標(biāo)識符的基本類型

Symbol 是使用帶有可選描述(name)的 Symbol() 調(diào)用創(chuàng)建的。

Symbol 總是不同的值,即使它們有相同的名字。如果我們希望同名的 Symbol 相等,那么我們應(yīng)該使用全局注冊表:Symbol.for(key) 返回(如果需要的話則創(chuàng)建)一個以 key 作為名字的全局 Symbol。使用 Symbol.for 多次調(diào)用 key 相同的 Symbol 時,返回的就是同一個 Symbol。

Symbol 有兩個主要的使用場景:

  • “隱藏” 對象屬性。如果我們想要向“屬于”另一個腳本或者庫的對象添加一個屬性,我們可以創(chuàng)建一個 Symbol 并使用它作為屬性的鍵。Symbol 屬性不會出現(xiàn)在 for..in 中,因此它不會意外地被與其他屬性一起處理。并且,它不會被直接訪問,因為另一個腳本沒有我們的 symbol。因此,該屬性將受到保護(hù),防止被意外使用或重寫。

因此我們可以使用 Symbol 屬性“秘密地”將一些東西隱藏到我們需要的對象中,但其他地方看不到它。

  • JavaScript 使用了許多系統(tǒng) Symbol,這些 Symbol 可以作為 Symbol.* 訪問。我們可以使用它們來改變一些內(nèi)置行為。例如,在本教程的后面部分,我們將使用 Symbol.iterator 來進(jìn)行 迭代 操作,使用 Symbol.toPrimitive 來設(shè)置 對象原始值的轉(zhuǎn)換 等等。

從技術(shù)上說,Symbol 不是 100% 隱藏的。有一個內(nèi)置方法Object.getOwnPropertySymbols(obj) 允許我們獲取所有的 Symbol。還有一個名為 Reflect.ownKeys(obj) 的方法可以返回一個對象的 所有 鍵,包括 Symbol。所以它們并不是真正的隱藏。但是大多數(shù)庫、內(nèi)置方法和語法結(jié)構(gòu)都沒有使用這些方法。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Javascript中常用類型的格式化方法小結(jié)

    Javascript中常用類型的格式化方法小結(jié)

    這篇文章主要給大家介紹了Javascript中常用類型的格式化方法,其中包括格式化浮點數(shù)、格式化有符號整數(shù)(int32)、格式化無符號整數(shù)(uint32)、格式化布爾值以及格式化字符串等,文中給出了詳細(xì)的示例代碼,有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-12-12
  • 淺談JavaScript節(jié)流和防抖函數(shù)

    淺談JavaScript節(jié)流和防抖函數(shù)

    這篇文章主要介紹了JavaScript節(jié)流和防抖函數(shù)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下
    2020-08-08
  • js動態(tài)創(chuàng)建表格,刪除行列的小例子

    js動態(tài)創(chuàng)建表格,刪除行列的小例子

    這篇文章介紹了js動態(tài)創(chuàng)建表格,刪除行列的實例代碼,有需要的朋友可以參考一下
    2013-07-07
  • 簡單實現(xiàn)js拖拽效果

    簡單實現(xiàn)js拖拽效果

    這篇文章主要教大家如何簡單實現(xiàn)js拖拽效果,很詳細(xì)的js拖拽效果實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • ES6中class類用法實例淺析

    ES6中class類用法實例淺析

    這篇文章主要介紹了ES6中class類用法,結(jié)合實例形式分析了ES6中類的實現(xiàn)方法與相關(guān)語法使用技巧,需要的朋友可以參考下
    2017-04-04
  • 在JavaScript中使用JSON數(shù)據(jù)

    在JavaScript中使用JSON數(shù)據(jù)

    JSON 是 JavaScript 原生格式,這意味著 在 JavaScript 中處理 JSON 數(shù)據(jù)不需要任何特殊的 API 或工具包,接下來由腳本之家小編給大家介紹在JavaScript中使用JSON數(shù)據(jù)的方法,感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • 代碼規(guī)范需要防微杜漸code?review6個小錯誤糾正

    代碼規(guī)范需要防微杜漸code?review6個小錯誤糾正

    這篇文章主要為大家介紹了代碼規(guī)范需要防微杜漸code?review中的6個小錯誤糾正,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • bootstrap輸入框組代碼分享

    bootstrap輸入框組代碼分享

    Bootstrap 支持的另一個特性,輸入框組,輸入框組擴(kuò)展自表單控件.下面小編給大家介紹bootstrap輸入框組的代碼,非常不錯具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧
    2016-06-06
  • JS與HTML結(jié)合實現(xiàn)流程進(jìn)度展示條思路詳解

    JS與HTML結(jié)合實現(xiàn)流程進(jìn)度展示條思路詳解

    基于js與html相結(jié)合實現(xiàn)的流程進(jìn)度展示條,非常實用,在各大網(wǎng)站都可以用到,下面小編給大家?guī)砹薐S與HTML結(jié)合實現(xiàn)流程進(jìn)度展示條思路詳解,需要的朋友參考下吧
    2017-09-09
  • 前端本地數(shù)據(jù)存儲的幾種常見方式總結(jié)

    前端本地數(shù)據(jù)存儲的幾種常見方式總結(jié)

    在前端開發(fā)中,本地數(shù)據(jù)存儲是實現(xiàn)客戶端數(shù)據(jù)持久化的關(guān)鍵技術(shù),以下是幾種常見的前端本地數(shù)據(jù)存儲方式,通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2025-01-01

最新評論

吴川市| 台东县| 靖边县| 绥江县| 奉新县| 彭州市| 苍梧县| 防城港市| 河北省| 郴州市| 双牌县| 特克斯县| 育儿| 扶绥县| 尚志市| 嘉义县| 涞源县| 宁德市| 德令哈市| 辉南县| 四平市| 阳原县| 新竹县| 怀仁县| 霍州市| 磐石市| 屏边| 株洲县| 云霄县| 花莲市| 神农架林区| 始兴县| 大丰市| 迭部县| 台中县| 宣恩县| 高雄市| 平乡县| 深泽县| 连江县| 宁乡县|