成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Javascript Symbol 隱匿的未來之星

wwolf / 2786人閱讀

摘要:通常,它做為一個(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等等

unscopeables
const 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);  //true
isConcatSpreadable

表示[].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"));  //-1
practice

可以通過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

相關(guān)文章

  • SegmentFault 受邀作為 2018 區(qū)塊鏈之星評審機(jī)構(gòu)

    摘要:為鼓勵創(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...

    Olivia 評論0 收藏0
  • ES6 for..of 和 Generator,從偽數(shù)組 jQuery 對象說起

    摘要:引用自可迭代對象和迭代器不以規(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è)...

    Harriet666 評論0 收藏0
  • 2016-JavaScript之星

    摘要:在,是當(dāng)之無愧的王者,贏得了與之間的戰(zhàn)爭,攻陷了的城池。于月發(fā)布了版本,這一版本為了更好的表現(xiàn)加入了渲染方式。前端框架這個(gè)前端框架清單可能是年疲勞的元兇之一。的創(chuàng)建者,目前在工作為尋找構(gòu)建簡單性和自主配置性之間的平衡做了很大的貢獻(xiàn)。 春節(jié)后的第一篇就從這個(gè)開始吧~本文已在前端早讀課公眾號上首發(fā) 原文鏈接 JavasScript社區(qū)在創(chuàng)新的道路上開足了馬力,曾經(jīng)流行過的也許一個(gè)月之后就過...

    Binguner 評論0 收藏0
  • 區(qū)塊鏈記賬原理

    摘要:本文首發(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)為與智能合約...

    mumumu 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<