在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 符號
生成器
箭頭函數(shù)
繼續(xù)迭代器
未來前景
簡介
非結(jié)構(gòu)化賦值
迭代器和 for-of 循環(huán)
代理
符號
模版字符串
let 和 const
容器
模塊

符號

什么是 ES6 的符號?

符號不是圖標(biāo)。

他們不是你可以在你的程序中使用的小圖片。

let http://wiki.jikexueyuan.com/project/es-six-deeply/images/1.png" alt="" />= http://wiki.jikexueyuan.com/project/es-six-deeply/images/0.png" alt="" /> × http://wiki.jikexueyuan.com/project/es-six-deeply/images/2.png" alt="" />; // SyntaxError

他們不是代表別的東西的文學(xué)的工具。

他們是絕對是與鈸不一樣的東西。

http://wiki.jikexueyuan.com/project/es-six-deeply/images/bo.jpg" alt="Alt text" />

在編程中使用鈸絕對不是一個好主意。他們有奔潰的趨勢。

所以,符號到底是什么?

第七種類型

從 1997 年 JavaScript 第一次被標(biāo)準(zhǔn)化,已經(jīng)出現(xiàn)了六種類型。直到 ES6,在 JS 程序的每個值都落入這些類別之一。

  • 未定義
  • 空值
  • 布爾
  • 數(shù)字
  • 字符串
  • 對象

每種類型是一組值。前五個組都是有限的。當(dāng)然,只有兩個布爾值,真與假,而且他們不會制造新的。但是有更多的數(shù)值和字符串值。該標(biāo)準(zhǔn)說,其有 18,437,736,874,454,810,627 個不同的數(shù)字(包括 NaN,則其名字為“不是一個數(shù)”的縮寫)。這與可能的字串的數(shù)量是不能相比的。我認(rèn)為字符串的數(shù)目可以是(2144,115,188,075,855,872 - 1)÷65,535...雖然我可能計算有誤。

然而,每組對象的值是開放式的。每個對象都是一個獨特的,珍貴的雪花。每一次你打開一個網(wǎng)頁,很多很多新的對象被創(chuàng)建。

ES6 符號是值,但它們不是字符串。他們不是對象。他們是新的東西:第七種類型的值。

一種簡單的小布爾值

有時,在一個 JavaScript 對象上藏匿一些真正屬于別人的額外的數(shù)據(jù)是非常方便的。

例如,假設(shè)你正在寫一個 JS 庫,其使用 CSS 過渡,使 DOM 元素在屏幕上壓縮。你可能已經(jīng)注意到,試圖將多個 CSS 轉(zhuǎn)換同時用于單個 div 是不起作用的。它會導(dǎo)致難看的,不連續(xù)的“跳躍”。你認(rèn)為你能解決這個問題,但首先你需要一種方法來搞清楚一個給定的元素是否已經(jīng)移動。

你怎么能解決這個問題?

一種方法是使用 CSS API 來詢問瀏覽器該元件是否被移動。但是,這聽起來有點小題大做。你的庫應(yīng)該已經(jīng)知道元素是移動的;那就是最開始設(shè)置其移動的代碼!

你真正想要的是一種能跟蹤哪些元素正在移動的方法。你可以使用一個數(shù)組紀(jì)錄所有運動的元素。每當(dāng)您的庫被調(diào)用,要使元素進行移動,你可以搜索數(shù)組來看看是否該元素已經(jīng)存在。

嗯。如果數(shù)組很大的話,線性搜索將是緩慢的。

你真正想要做的只是設(shè)置元素的標(biāo)志:

if (element.isMoving) {
  smoothAnimations(element);
}
element.isMoving = true;

這里也有幾個可能的問題。他們都與這樣的事實相關(guān),那就是你的代碼不是唯一一個使用 DOM 的代碼。

  1. 其他的使用 for-in 或者 Object.keys( ) 的代碼可能會在你創(chuàng)建的屬性上遇到問題。

  2. 如果一些聰明的庫作者可能已經(jīng)先想到了這個技術(shù),那么你的庫可能與現(xiàn)有的庫的互動不是很好。

  3. 其他一些聰明的庫的作者可能在未來想到這個技術(shù),和您的庫可能與未來的庫的互動不是很好。

  4. 該標(biāo)準(zhǔn)委員會可以決定給所有元素添加一個 .isMoving() 方法。然后,你真的被大清洗了!

當(dāng)然,你可以通過選擇一個太繁瑣或太傻了字符串來解決最后三個問題,沒有人會用下面的方式進行命名:

if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) {
  smoothAnimations(element);
}
element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;

這看起來似乎不太值得我們眼睛的疲勞。

你可以通過使用密碼學(xué)的知識為這個屬性生成唯一的名字:

// get 1024 Unicode characters of gibberish
var isMoving = SecureRandom.generateName();

...

if (element[isMoving]) {
  smoothAnimations(element);
}
element[isMoving] = true;

object[name] 語法讓你可以使用任何字符串作為一個屬性的名字。所以這將是有用的:因為碰撞幾乎是不可能的,你的代碼看起來不錯。

但是這也會導(dǎo)致很糟糕的代碼調(diào)試過程。每次你對一個有該屬性的元素進行 console.log( ) 操作,你將會看到一個龐大的垃圾字符串。同時,如果你需要不止一個像這樣的屬性呢?你怎么直接保留他們?當(dāng)你重載他們的時候,他們每次都會有不同的名字。

為什么這是如此的困難?我們只是想要一個小布爾值。

符號就是答案

符號是值,編程者可以創(chuàng)建并像屬性關(guān)鍵字一樣使用,且不會有名字沖突的危險。

var mySymbol = Symbol();

調(diào)用 Symbol( ) 可以創(chuàng)建一個新的符號,且具有唯一的值。

就像一個字符串或者數(shù)值,你可以使用一個符號作為一個屬性關(guān)鍵字。因為其不同于任何字符串,這個符號鍵屬性被用來保證不與其他的屬性相沖突。

obj[mySymbol] = "ok!";  // guaranteed not to collide
console.log(obj[mySymbol]);  // ok!

這里就是你如何在上述討論的情況下使用一個符號:

// create a unique symbol
var isMoving = Symbol("isMoving");

...

if (element[isMoving]) {
  smoothAnimations(element);
}
element[isMoving] = true;

下述是關(guān)于這個代碼的一些筆記。

  • 在符號( "isMoving")中的字符串 "isMoving"被稱為一個描述。它有助于代碼調(diào)試。當(dāng)你給 console.log( )寫一個符號的時候,當(dāng)你通過使用 .toString( )將其轉(zhuǎn)化為一個字符串的時候,亦或者可能在錯誤信息中你可以感覺到它的好處。就是這樣的。

  • element[isMoving] 被稱為一個符號鍵屬性。它只是一種名字是一個符號的屬性,除此之外,它是在各方面都是一個正常屬性。

  • 如數(shù)組元素相似,符號鍵屬性不能像在 obj.name 中用點語法訪問。他們必須使用方括號進行訪問。

  • 如果你已經(jīng)拿到了符號,訪問符號鍵屬性是微不足道的。上面的例子就是說明如何獲取和設(shè)置 element[isMoving],而且我們還可以詢問是否為 (isMoving in element),或者如果我們需要,我們甚至可以使用 delete element[isMoving]。

  • 另一方面,只要 isMoving 是在范圍內(nèi),所有都是可能的。這使得符號成為一種薄封裝機制:若一個模塊為自己創(chuàng)建了幾個符號,其可以在任何對象上使用他們這些符號,而不必?fù)?dān)心與其他的代碼創(chuàng)建的屬性發(fā)生沖突。

由于符號關(guān)鍵字被設(shè)計為避免沖突的,JavaScript 最常見的對象檢測功能簡單地忽視了符號鍵。例如,一個 for-in 循環(huán),其僅在對象的字符串關(guān)鍵字上循環(huán)。符號關(guān)鍵字是被跳過的。 Object.keys(obj) 和 Object.getOwnPropertyNames(obj) 也是這樣做的。但符號不完全是私有的:它可以使用新的 API Object.getOwnPropertySymbols(obj) 來列出一個對象的符號關(guān)鍵字。另一個新的 API,Reflect.ownKeys(obj),返回字符串和符號關(guān)鍵字。(我們將在后續(xù)的博客中繼續(xù)討論 Reflect API。)

庫和框架很可能會發(fā)現(xiàn)符號的很多用途,如我們以后會看到的一樣,語言本身使用他們是為了更加廣泛的用途。

但是符號到底是什么?

> typeof Symbol()
"symbol"

符號不像任何其他東西。

他們一旦創(chuàng)建就不可改變。你不能對它們進行屬性設(shè)置(如果你在嚴(yán)格模式下嘗試,你會得到一個類型錯誤)。它們可以是屬性的名稱。這些都是與字符串類似的性質(zhì)。

在另一方面,每個符號都是獨一無二的,與所有其他的符號都不相同(即使其他人有相同的描述)。同時,你可以很輕松地創(chuàng)建新的符號。這些是與對象相類似的性質(zhì)。

ES6 符號類似于相對傳統(tǒng)的語言中的 Lisp 和 Ruby,但其又沒有非常緊密的集成于語言中。在 Lisp 中,所有標(biāo)識符都是符號。在 JS 中,標(biāo)識符和大部分屬性關(guān)鍵字仍然被認(rèn)為是字符串。符號只是一種額外的選擇。

關(guān)于符號做個快速的警告:與幾乎所有其他語言都不同的是,它們不能自動轉(zhuǎn)換為字符串。試圖用講符號和字符串串聯(lián)起來將導(dǎo)致一個類型錯誤。

> var sym = Symbol("<3");
> "your symbol is " + sym
// TypeError: can't convert symbol to string
> `your symbol is ${sym}`
// TypeError: can't convert symbol to string

你可以通過明確的將一個符號轉(zhuǎn)換為一個字符串來避免發(fā)生類型錯誤。方法就是 String(sym) 或者 sym.toString( )。

三種符號集合

獲取一個符號有三種方式。

  • 調(diào)用 Symbol( )。正如我們已經(jīng)討論過的,每次被調(diào)用后,其都會返回一個新的獨一無二的符號。

  • 調(diào)用 Symbol.for(string)。訪問一組已經(jīng)存在的字符串被稱為符號注冊。不同于由 Symbol( ) 定義的獨特的符號,在符號注冊表中的符號是共享的。如果你調(diào)用Symbol.for("cat") 三十多次,其每次都將返回相同的符號。當(dāng)多個網(wǎng)頁,或同一網(wǎng)頁內(nèi)多個模塊需要共享一個符號時,注冊表是有用的。

  • 像 Symbol.iterator 一樣使用符號,其是有標(biāo)準(zhǔn)定義的。有些符號是由標(biāo)準(zhǔn)自身定義的。每一個都有其特殊的目的。

如果你仍然不確定符號是否都是都如此有效,這里最后的部分將是有趣的,因為他們將會展示符號是如何在實際中被證明是有效的。

ES6 規(guī)范如何使用眾所周知的符號

我們已經(jīng)看到,ES6 使用符號作為一種避免與現(xiàn)有代碼的沖突的方法。幾個星期前,在講迭代器的博客中,我們看到,循環(huán) for (var item of myArray) 通過調(diào)用 myArray[Symbol.iterator]( ) 方法開始。我提到的這個方法已經(jīng)被稱為 myArray.iterator( ),但符號能更好得向后兼容。

現(xiàn)在我們知道了符號是怎么一回事了,因此很容易理解為什么這樣做且這樣做意味著什么。

這里還有幾個地方 ES6 使用了眾所周知的符號。(這些功能都還沒有在火狐瀏覽器中實現(xiàn)。)

  • 使得 instanceof 可擴展。在 ES6 中,語句 object instanceof constructor 被具體描述為構(gòu)造的一個方法:constructor[Symbol.hasInstance](object)。這就意味著這是可擴展的。

  • 消除了新功能和舊代碼之間的沖突。這真的很復(fù)雜,但是我們發(fā)現(xiàn) ES6 的數(shù)組方法只是通過其存在性就使現(xiàn)有的網(wǎng)站奔潰了。其它的 Web 標(biāo)準(zhǔn)有類似的問題:在瀏覽器里簡單地增加新的方法也會使現(xiàn)有的網(wǎng)站崩潰。然而,奔潰主要是由于一種叫做動態(tài)作用域的東西,所以 ES6 引入了一個特殊的符號,Symbol.unscopables,即 Web 標(biāo)準(zhǔn)可以用這個符號防止某些方法被卷入到動態(tài)作用域中。

  • 支持新類型的字符串匹配。在 ES5 中,str.match(myObject) 試圖將 myObject 轉(zhuǎn)換為一個正則表達式。在 ES6 中,它首先檢查 myObject 是否有 myObject[Symbol.match](str) 的方法?,F(xiàn)在的庫可以提供自定義字符串解析類,其可以使用在任何可以使用正則表達式對象的地方。

上述的任意一個的用途都比較窄。很難從這些功能自身來看其對我們的代碼產(chǎn)生的重大影響。從長遠來看更有趣。著名的符號是 JavaScript 對 PHP 和 Python 的 __doubleUnderscores 的改進版本。該標(biāo)準(zhǔn)將在未來,在對你現(xiàn)有的代碼不產(chǎn)生風(fēng)險的前提下,使用他們在語言中添加新的掛鉤,

我什么時候能使用 ES6 符號?

符號已經(jīng)在火狐瀏覽器第 36 版本和谷歌瀏覽器第 38 版本中實現(xiàn)了。我自己也在火狐瀏覽器上進行了實現(xiàn),所以如果你的符號曾經(jīng)表現(xiàn)得像鈸,你就會知道應(yīng)該向誰傾訴。

為了支持那些對 ES6 符號還沒有原生支持的瀏覽器,你可以使用一個 polyfill,如 core.js。由于符號與以前語言中的東西是完全不像的,polyfill 也不是完美的。請閱讀注意事項

下章我們將討論一些 JavaScript 期待已久且終于在 ES6 中到來的功能,并吐糟一下它不好的地方。我們將開始兩個可以追溯到編程最初時光的功能。我們將繼續(xù)討論兩個非常相似的但由 ephemerons 搭載的功能。

上一篇:非結(jié)構(gòu)化賦值下一篇:容器