摘要:通常,它做為一個偏功能性的標記來表示,在全劇中它是唯一的。并且使用來生成,會在存入當前全局上下文中一個結構中,我們稱它為顧名思義,它是全局的,所以使用時我們需要謹慎,尤其是在大型項目中。
ES6中基礎類型增加到了7種,比上一個版本多了一個Symbol,貌似出現了很長時間,但卻因沒有使用場景,一直當作一個概念層來理解它,我想,用它的最好的方式,還是要主動的去深入了解它吧,所以我從基礎部分和總結的實用場景來分析這個特性。已經了解使用方法或者時間緊迫者可以從實用場景一節開始閱讀
base首先,它給我的第一感覺就是ES6做出了很多釋放語言特性方面的改變,它能讓我們更加了解語言內部機制,Symbol以對象的鍵值定義,比如
let key = Symbol("test"); let obj = {}; obj[key] = "alone"; obj[key]; // "alone"
Symbol正如其名,表示一個唯一的標示,以屬性的方式存在于對象當中,它接收一個參數,沒有實質的作用,只是為了做一個描述。以上我們通過直接量的方式來定義它,并且取值時,也需要使用key進行讀取,如果出現跨作用域的情況,是不是就不能獲取了?
function sent(key){ accept({[key]:"2018"}) } function accept(obj) { obj[???] //我怎么拌? }
以上兩個作用域中,如果不把key傳遞過來,是無法讀取的,一個屬性還好,但是如果多了,那么靠參數傳遞key是不現實的. 在這種情況下,我們可以使用 Symbol.for 來為它再添加一個標示,它接受一個參數String{key}。通常,它做為一個偏功能性的標記來表示,在全劇中它是唯一的。
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 來生成,會在存入當前全局上下文中一個結構中,我們稱它為GlobalSymbolRegistry , 顧名思義,它是全局的,所以使用key時我們需要謹慎,尤其是在大型項目中。
需要還注意以下幾點:
讀取它需要使用 getOwnPropertySymbols 方法,具體請參看MDN
Symbol() !== Symbol() but Symbol.for("t") === Symbol.for("t")
GlobalSymbolRegistry對象存在于當前窗口進程中,直到關閉窗口,才清除掉
目前的瀏覽器版本中把Symbol打印出來是字符串的格式,并沒有顯示具體的對象結構,我們可以直接打印 Symbol,來查看對應的prototype屬性以及內部方法,所以 Symbol().__proto__ === Symbol.prototype
在使用 Symbol 做key值時,它經歷了以下步驟
如果指向對象是沒有定義的則拋出類型錯誤
如果描述符為undefined則為""
把描述符轉換為String格式
生成唯一的key,并返回
最后一步,把這個key賦給對象,并以Symbol(des)的方式顯示,其內部還是以key為準,所以 Symbol() !== Symbol() ,即便他們看起來都是 字符串的"Symbol()"
所以這樣寫也是可以的,但是貌似沒有什么意義
var n = 1; var key = Symbol("numer") n[key] = ‘Symbol Number’
n[key]的時候把n隱式轉換成封裝對象,并為他添加Symbol,但并沒有辦法去通過封裝對象回訪這個Symbol
除了單純的用key以外,在Symbol類下還有一些有意思的方法,following :
iterator為指向對象添加 iterator 接口,比如使用數組解構或者使用for of,它接受一個generator函數
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使用數據解構,還可以使用for of
let values = []; for (let value of obj) { values.push(value) } values; //[1,2,3]
注:ES6中Map,Set,數組和添加了Iterator接口的對象,擁有Iterator接口.
asyncIterator這不是ES6中的特性,貌似放到了ES7中,可以提前意淫一下如下代碼:
for await (const line of readLines(filePath)) { console.log(line); }toPrimitive
在對對象類型進行轉換時,會進行一次 toPrimitive,利用這個Symbol可以改變目標對象的轉換規則,改變了以前的 "[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" 的,其他正常,這樣就可以定義轉對象類型的轉換規則了。
toStringTag在javascript一切皆為對象,而在每個對象中,都會有一個內部屬性[[Class]]表示其對象類型,這在Symbol.toStringTag,中是可以修改的,也就是說 "[object Object]" 后邊的字符串是可自定義的
let obj = { [Symbol.toStringTag]:"custom" } Object.prototype.toString(obj); // [object Object] obj.toString(); //[object custom]
通常我們使用Object.prototype.toString讀取對象屬性,正是因為向后兼容,規范在對象自身的toString上實現了這種特性,而老式方法依舊使用。但是我們可以使用以下方式:
obj = { [Symbol.toStringTag]:"custom" get [Symbol.toStringTag](){ return "custom" } } Object.prototype.toString.call(obj)
我們把obj傳入執行toString,可以達到這種效果,可以預想es6中,Object.toString是受到上下文的影響的. 顯然,我們上面的兩個例子都是獲取的Object.prototype.toString 兩者有很大區別,只有它才能準確轉換,如果你的toString不全等于它,那是無法轉換的,比如
var n = new Number(); n[Symbol.toStringTag] = 123; n.toString(); // “0”
太幼稚了,太無聊了?,Number私有的toString是直接把[[PrimitiveValue]]轉換成了字符串,這里大家要千萬留心,不要誤認為所有的對象添加了Symbol.toStringTag都可以改變,如果當前對象不是純對象,那么你可以為此對象添加一個 getter 返回對應的類型,這樣外部在使用Object...call的時,會獲取自定的類型。所以,這需要外部配合使用,你添加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); }
這個功能我感覺可用性為0,基本不用,with就是據對禁止的.
hasInstance對于 instance運算符,為此操作添加一個鉤子,第一參數是instance的左值,我們可以返回true|false來定義運算符的返回值
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是否可以展開,默認是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]
只有在數組中這個symbol屬性為false,concat操作時,就不會去解構。那么是不是意味著屬性設置為ture,沒有意義了?對于數組來說是的,因為它默認就是true,可是對于類數組對象,它還有一個小功能:
// (續) arr.concat({length:2,0:3,1:4,[Symbol.isConcatSpreadable]:true}) //[1,2,3,4]match & replace & split & search
一些字符串的操作方法,一起都說了,大概都一個意思,就是接受一個對象,然后實現一個鉤子處理的函數,并返回其處理結果,它們都是可以接收正則的方法,在ES6之前,如果我們需要對字符串有比較復雜的操作基本上都是在方法外部的,必
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實現以上的功能性方法,比如添加 Iterator 接口,讓對象隊友接口特性,實際開發中,我估計很少會用到,倒是覺得 sanycIterator 是未來的前景,目前還在草案階段
對于Symbol做為鍵值的作用,很尷尬,實際開發中,這個我也沒使用過,目前為止,只需要記住它有unique性,比如我們想要在一個對象中添加兩個一樣的key名,這種需求很不常見,
var firstPerson = Symbol("peter"); var secondPerson = Symbol("peter"); var persons = {[firstPerson]:"first", [secondPerson]:"pan"};總結
Symbol更多的是在使用和語言本身層面暴露更多的使用方式和特性(on Object type),是的,它只以key的方式存在Object當中,在一切皆為對象中,它為 Next ECMScript Standard 提供了更多的可能性擴展性,這也是ES6中做的最大改變方面之一,雖不常用但我們還是要總結學習一下,以便在極端情況下應變自如,如果有什么文章中沒有涉及到的點,歡迎補充! 注: 尤其是使用場景方面
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94514.html
摘要:為鼓勵創新技術及推動區塊鏈應用落地,進一步推動創新發展,本次論壇同步籌備舉辦區塊鏈之星年度評選。初選強共計獲得有效票數枚,參與投票人數近萬。最終結果將于月日美國硅谷舉辦的中美創投峰會區塊鏈論壇正式公布,并為獲獎者頒獎。 如你所見,有一大筆財富和價值正在被區塊鏈創造出來。正如 Blockstack 的創始人 Ryan Shea 和 AngelList 創始人 Naval Ravikant...
摘要:引用自可迭代對象和迭代器不以規矩,不成方圓為了使某個對象成為可迭代對象象,它必須實現方法,也就是說,它得有一個是的屬性。的遍歷,絕對應該用。 pseudo 英 [sju:d??] 美 [su:do?]adj.假的,虛偽的n.[口]假冒的人,偽君子 pseudo-array 英 [sju:d???re?] 美 [sju:d???re?][計] 偽數組 jQuery 對象是偽數組 兩個...
摘要:在,是當之無愧的王者,贏得了與之間的戰爭,攻陷了的城池。于月發布了版本,這一版本為了更好的表現加入了渲染方式。前端框架這個前端框架清單可能是年疲勞的元兇之一。的創建者,目前在工作為尋找構建簡單性和自主配置性之間的平衡做了很大的貢獻。 春節后的第一篇就從這個開始吧~本文已在前端早讀課公眾號上首發 原文鏈接 JavasScript社區在創新的道路上開足了馬力,曾經流行過的也許一個月之后就過...
閱讀 2315·2021-11-24 10:33
閱讀 1385·2019-08-30 15:43
閱讀 3276·2019-08-29 17:24
閱讀 3481·2019-08-29 14:21
閱讀 2220·2019-08-29 13:59
閱讀 1735·2019-08-29 11:12
閱讀 2811·2019-08-28 18:00
閱讀 1849·2019-08-26 12:17