摘要:通常,它做為一個(gè)偏功能性的標(biāo)記來表示,在全劇中它是唯一的。并且使用來生成,會在存入當(dāng)前全局上下文中一個(gè)結(jié)構(gòu)中,我們稱它為顧名思義,它是全局的,所以使用時(shí)我們需要謹(jǐn)慎,尤其是在大型項(xiàng)目中。
ES6中基礎(chǔ)類型增加到了7種,比上一個(gè)版本多了一個(gè)Symbol,貌似出現(xiàn)了很長時(shí)間,但卻因沒有使用場景,一直當(dāng)作一個(gè)概念層來理解它,我想,用它的最好的方式,還是要主動的去深入了解它吧,所以我從基礎(chǔ)部分和總結(jié)的實(shí)用場景來分析這個(gè)特性。已經(jīng)了解使用方法或者時(shí)間緊迫者可以從實(shí)用場景一節(jié)開始閱讀
base首先,它給我的第一感覺就是ES6做出了很多釋放語言特性方面的改變,它能讓我們更加了解語言內(nèi)部機(jī)制,Symbol以對象的鍵值定義,比如
let key = Symbol("test"); let obj = {}; obj[key] = "alone"; obj[key]; // "alone"
Symbol正如其名,表示一個(gè)唯一的標(biāo)示,以屬性的方式存在于對象當(dāng)中,它接收一個(gè)參數(shù),沒有實(shí)質(zhì)的作用,只是為了做一個(gè)描述。以上我們通過直接量的方式來定義它,并且取值時(shí),也需要使用key進(jìn)行讀取,如果出現(xiàn)跨作用域的情況,是不是就不能獲取了?
function sent(key){ accept({[key]:"2018"}) } function accept(obj) { obj[???] //我怎么拌? }
以上兩個(gè)作用域中,如果不把key傳遞過來,是無法讀取的,一個(gè)屬性還好,但是如果多了,那么靠參數(shù)傳遞key是不現(xiàn)實(shí)的. 在這種情況下,我們可以使用 Symbol.for 來為它再添加一個(gè)標(biāo)示,它接受一個(gè)參數(shù)String{key}。通常,它做為一個(gè)偏功能性的標(biāo)記來表示,在全劇中它是唯一的。
function sent(key){ return accept({[key]:"2018"},key) } function accept(obj,key) { console.log(Symbol.keyFor(key)) //CURRENT_YEAR return obj[Symbol.for(Symbol.keyFor(key))] //CURRENT_YEAR } sent(Symbol.for("CURRENT_YEAR"))
并且使用 Symbol.for 來生成,會在存入當(dāng)前全局上下文中一個(gè)結(jié)構(gòu)中,我們稱它為GlobalSymbolRegistry , 顧名思義,它是全局的,所以使用key時(shí)我們需要謹(jǐn)慎,尤其是在大型項(xiàng)目中。
需要還注意以下幾點(diǎn):
讀取它需要使用 getOwnPropertySymbols 方法,具體請參看MDN
Symbol() !== Symbol() but Symbol.for("t") === Symbol.for("t")
GlobalSymbolRegistry對象存在于當(dāng)前窗口進(jìn)程中,直到關(guān)閉窗口,才清除掉
目前的瀏覽器版本中把Symbol打印出來是字符串的格式,并沒有顯示具體的對象結(jié)構(gòu),我們可以直接打印 Symbol,來查看對應(yīng)的prototype屬性以及內(nèi)部方法,所以 Symbol().__proto__ === Symbol.prototype
在使用 Symbol 做key值時(shí),它經(jīng)歷了以下步驟
如果指向?qū)ο笫菦]有定義的則拋出類型錯誤
如果描述符為undefined則為""
把描述符轉(zhuǎn)換為String格式
生成唯一的key,并返回
最后一步,把這個(gè)key賦給對象,并以Symbol(des)的方式顯示,其內(nèi)部還是以key為準(zhǔn),所以 Symbol() !== Symbol() ,即便他們看起來都是 字符串的"Symbol()"
所以這樣寫也是可以的,但是貌似沒有什么意義
var n = 1; var key = Symbol("numer") n[key] = ‘Symbol Number’
n[key]的時(shí)候把n隱式轉(zhuǎn)換成封裝對象,并為他添加Symbol,但并沒有辦法去通過封裝對象回訪這個(gè)Symbol
除了單純的用key以外,在Symbol類下還有一些有意思的方法,following :
iterator為指向?qū)ο筇砑?iterator 接口,比如使用數(shù)組解構(gòu)或者使用for of,它接受一個(gè)generator函數(shù)
class IteratorExec { constructor(){ this.count = 1 } *[Symbol.iterator] = function* (){ yield this.count++; yield this.count++; yield this.count++; } } let obj = new IteratorExec() [...obj] //[1,2,3]
通過添加iterator使用數(shù)據(jù)解構(gòu),還可以使用for of
let values = []; for (let value of obj) { values.push(value) } values; //[1,2,3]
注:ES6中Map,Set,數(shù)組和添加了Iterator接口的對象,擁有Iterator接口.
asyncIterator這不是ES6中的特性,貌似放到了ES7中,可以提前意淫一下如下代碼:
for await (const line of readLines(filePath)) { console.log(line); }toPrimitive
在對對象類型進(jìn)行轉(zhuǎn)換時(shí),會進(jìn)行一次 toPrimitive,利用這個(gè)Symbol可以改變目標(biāo)對象的轉(zhuǎn)換規(guī)則,改變了以前的 "[object Object]"的固定形式
let obj = { [Symbol.toPrimitive](hint){ switch(hint){ case "number": return 5; case "string": return "string"; case "default": return "default" } } } obj+11 // "default11" obj*2 // 10
這里需要注意+ Number操作是不屬于 "number" 的,其他正常,這樣就可以定義轉(zhuǎn)對象類型的轉(zhuǎn)換規(guī)則了。
toStringTag在javascript一切皆為對象,而在每個(gè)對象中,都會有一個(gè)內(nèi)部屬性[[Class]]表示其對象類型,這在Symbol.toStringTag,中是可以修改的,也就是說 "[object Object]" 后邊的字符串是可自定義的
let obj = { [Symbol.toStringTag]:"custom" } Object.prototype.toString(obj); // [object Object] obj.toString(); //[object custom]
通常我們使用Object.prototype.toString讀取對象屬性,正是因?yàn)橄蚝蠹嫒?,?guī)范在對象自身的toString上實(shí)現(xiàn)了這種特性,而老式方法依舊使用。但是我們可以使用以下方式:
obj = { [Symbol.toStringTag]:"custom" get [Symbol.toStringTag](){ return "custom" } } Object.prototype.toString.call(obj)
我們把obj傳入執(zhí)行toString,可以達(dá)到這種效果,可以預(yù)想es6中,Object.toString是受到上下文的影響的. 顯然,我們上面的兩個(gè)例子都是獲取的Object.prototype.toString 兩者有很大區(qū)別,只有它才能準(zhǔn)確轉(zhuǎn)換,如果你的toString不全等于它,那是無法轉(zhuǎn)換的,比如
var n = new Number(); n[Symbol.toStringTag] = 123; n.toString(); // “0”
太幼稚了,太無聊了?,Number私有的toString是直接把[[PrimitiveValue]]轉(zhuǎn)換成了字符串,這里大家要千萬留心,不要誤認(rèn)為所有的對象添加了Symbol.toStringTag都可以改變,如果當(dāng)前對象不是純對象,那么你可以為此對象添加一個(gè) getter 返回對應(yīng)的類型,這樣外部在使用Object...call的時(shí),會獲取自定的類型。所以,這需要外部配合使用,你添加getter,人家不call你也是沒辦法的。
另外Symbol暴露了幾種為原生對象定義了一些類型,比如
Math.toString(); //[object Math]
其他類型有 JSON, Promise, Map, TypedArray, DataView, ArrayBuffer, Genterator等等
unscopeablesconst object1 = { property1: 42 }; object1[Symbol.unscopables] = { property1: true }; with (object1) { console.log(property1); }
這個(gè)功能我感覺可用性為0,基本不用,with就是據(jù)對禁止的.
hasInstance對于 instance運(yùn)算符,為此操作添加一個(gè)鉤子,第一參數(shù)是instance的左值,我們可以返回true|false來定義運(yùn)算符的返回值
var obj1 = { [Symbol.hasInstance](instance){ return Array.isArray(Array) } } class Array1 { static [Symbol.hasInstance](instance) { return Array.isArray(instance); } } [] instance obj1 //true console.log([] instanceof Array1); //trueisConcatSpreadable
表示[].concat是否可以展開,默認(rèn)是true.
let arr = [1,2]; arr.concat([3,4],5) //[1,2,3,4,5] arr[Symbol.isConcatSpreadable] = false; arr.concat([3,4],5) //[[1,2],3,4,5] // 也可以把[3,4]提出來處理 let arr2 = [3,4] arr2[Symbol.isConcatSpreadable] = false; arr.concat(arr2,5); //[[1,2],[3,4],5]
只有在數(shù)組中這個(gè)symbol屬性為false,concat操作時(shí),就不會去解構(gòu)。那么是不是意味著屬性設(shè)置為ture,沒有意義了?對于數(shù)組來說是的,因?yàn)樗J(rèn)就是true,可是對于類數(shù)組對象,它還有一個(gè)小功能:
// (續(xù)) arr.concat({length:2,0:3,1:4,[Symbol.isConcatSpreadable]:true}) //[1,2,3,4]match & replace & split & search
一些字符串的操作方法,一起都說了,大概都一個(gè)意思,就是接受一個(gè)對象,然后實(shí)現(xiàn)一個(gè)鉤子處理的函數(shù),并返回其處理結(jié)果,它們都是可以接收正則的方法,在ES6之前,如果我們需要對字符串有比較復(fù)雜的操作基本上都是在方法外部的,必
class MyMatch { [Symbol.match](string){return string.indexOf("world") } } "hello world".match(new MyMatch()); //6 class MyReplace{ [Symbol.replace](string) { return "def" } } "abcdef".replace(new MyReplace(),"xxx"); //"abcxxx" class mySplit { [Symbol.split](val){ return val.split("-"); } } "123-123-123".split(new mySplit()); //["123","123","123"] class MySearch { constructor(value) { this.value = value; } [Symbol.search](string) { return string.indexOf(this.value); } } var fooSearch = "foobar".search(new MySearch("foo")); //0 var barSearch = "foobar".search(new MySearch("bar")); //3 var bazSearch = "foobar".search(new MySearch("baz")); //-1practice
可以通過Symbol實(shí)現(xiàn)以上的功能性方法,比如添加 Iterator 接口,讓對象隊(duì)友接口特性,實(shí)際開發(fā)中,我估計(jì)很少會用到,倒是覺得 sanycIterator 是未來的前景,目前還在草案階段
對于Symbol做為鍵值的作用,很尷尬,實(shí)際開發(fā)中,這個(gè)我也沒使用過,目前為止,只需要記住它有unique性,比如我們想要在一個(gè)對象中添加兩個(gè)一樣的key名,這種需求很不常見,
var firstPerson = Symbol("peter"); var secondPerson = Symbol("peter"); var persons = {[firstPerson]:"first", [secondPerson]:"pan"};總結(jié)
Symbol更多的是在使用和語言本身層面暴露更多的使用方式和特性(on Object type),是的,它只以key的方式存在Object當(dāng)中,在一切皆為對象中,它為 Next ECMScript Standard 提供了更多的可能性擴(kuò)展性,這也是ES6中做的最大改變方面之一,雖不常用但我們還是要總結(jié)學(xué)習(xí)一下,以便在極端情況下應(yīng)變自如,如果有什么文章中沒有涉及到的點(diǎn),歡迎補(bǔ)充! 注: 尤其是使用場景方面
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94514.html
摘要:為鼓勵創(chuàng)新技術(shù)及推動區(qū)塊鏈應(yīng)用落地,進(jìn)一步推動創(chuàng)新發(fā)展,本次論壇同步籌備舉辦區(qū)塊鏈之星年度評選。初選強(qiáng)共計(jì)獲得有效票數(shù)枚,參與投票人數(shù)近萬。最終結(jié)果將于月日美國硅谷舉辦的中美創(chuàng)投峰會區(qū)塊鏈論壇正式公布,并為獲獎?wù)哳C獎。 如你所見,有一大筆財(cái)富和價(jià)值正在被區(qū)塊鏈創(chuàng)造出來。正如 Blockstack 的創(chuàng)始人 Ryan Shea 和 AngelList 創(chuàng)始人 Naval Ravikant...
摘要:引用自可迭代對象和迭代器不以規(guī)矩,不成方圓為了使某個(gè)對象成為可迭代對象象,它必須實(shí)現(xiàn)方法,也就是說,它得有一個(gè)是的屬性。的遍歷,絕對應(yīng)該用。 pseudo 英 [sju:d??] 美 [su:do?]adj.假的,虛偽的n.[口]假冒的人,偽君子 pseudo-array 英 [sju:d???re?] 美 [sju:d???re?][計(jì)] 偽數(shù)組 jQuery 對象是偽數(shù)組 兩個(gè)...
摘要:在,是當(dāng)之無愧的王者,贏得了與之間的戰(zhàn)爭,攻陷了的城池。于月發(fā)布了版本,這一版本為了更好的表現(xiàn)加入了渲染方式。前端框架這個(gè)前端框架清單可能是年疲勞的元兇之一。的創(chuàng)建者,目前在工作為尋找構(gòu)建簡單性和自主配置性之間的平衡做了很大的貢獻(xiàn)。 春節(jié)后的第一篇就從這個(gè)開始吧~本文已在前端早讀課公眾號上首發(fā) 原文鏈接 JavasScript社區(qū)在創(chuàng)新的道路上開足了馬力,曾經(jīng)流行過的也許一個(gè)月之后就過...
摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接區(qū)塊鏈記賬原理原文已更新,請讀者前往原文閱讀區(qū)塊鏈?zhǔn)且粋€(gè)基于密碼學(xué)安全的分布式賬本,是一個(gè)方便驗(yàn)證,不可篡改的賬本。哈希函數(shù)在講區(qū)塊鏈記賬之前,先說明一下哈希函數(shù)。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:區(qū)塊鏈記賬原理原文已更新,請讀者前往原文閱讀 區(qū)塊鏈(1.0)是一個(gè)基于密碼學(xué)安全的分布式賬本,是一個(gè)方便驗(yàn)證,不可篡改的賬本。 通常認(rèn)為與智能合約...
閱讀 2333·2021-11-24 10:33
閱讀 1396·2019-08-30 15:43
閱讀 3289·2019-08-29 17:24
閱讀 3496·2019-08-29 14:21
閱讀 2235·2019-08-29 13:59
閱讀 1749·2019-08-29 11:12
閱讀 2821·2019-08-28 18:00
閱讀 1865·2019-08-26 12:17