Symbol

Symbol類型是ES6中新加入的一種原始類型紧帕。

每個(gè)從Symbol()返回的symbol值都是唯一的。一個(gè)symbol值能作為對(duì)象屬性的標(biāo)識(shí)符悴侵;這是該數(shù)據(jù)類型僅有的目的箱叁。

下面來看看Symbol類型具有哪些特性。

Symbol的特性

1.獨(dú)一無二

直接使用Symbol()創(chuàng)建新的symbol變量积蔚,可選用一個(gè)字符串用于描述意鲸。當(dāng)參數(shù)為對(duì)象時(shí),將調(diào)用對(duì)象的toString()方法尽爆。

var sym1 = Symbol();  // Symbol() 
var sym2 = Symbol('ConardLi');  // Symbol(ConardLi)
var sym3 = Symbol('ConardLi');  // Symbol(ConardLi)
var sym4 = Symbol({name:'ConardLi'}); // Symbol([object Object])
console.log(sym2 === sym3);  // false

我們用兩個(gè)相同的字符串創(chuàng)建兩個(gè)Symbol變量怎顾,它們是不相等的,可見每個(gè)Symbol變量都是獨(dú)一無二的漱贱。

如果我們想創(chuàng)造兩個(gè)相等的Symbol變量槐雾,可以使用Symbol.for(key)。

使用給定的key搜索現(xiàn)有的symbol幅狮,如果找到則返回該symbol募强。否則將使用給定的key在全局symbol注冊(cè)表中創(chuàng)建一個(gè)新的symbol株灸。

var sym1 = Symbol.for('ConardLi');
var sym2 = Symbol.for('ConardLi');
console.log(sym1 === sym2); // true

原始類型

注意是使用Symbol()函數(shù)創(chuàng)建symbol變量,并非使用構(gòu)造函數(shù)擎值,使用new操作符會(huì)直接報(bào)錯(cuò)慌烧。

new Symbol(); // Uncaught TypeError: Symbol is not a constructor

我們可以使用typeof運(yùn)算符判斷一個(gè)Symbol類型:

typeof Symbol() === 'symbol'
typeof Symbol('ConardLi') === 'symbol'

不可枚舉

當(dāng)使用Symbol作為對(duì)象屬性時(shí),可以保證對(duì)象不會(huì)出現(xiàn)重名屬性鸠儿,調(diào)用for...in不能將其枚舉出來屹蚊,另外調(diào)用Object.getOwnPropertyNames、Object.keys()也不能獲取Symbol屬性捆交。

可以調(diào)用Object.getOwnPropertySymbols()用于專門獲取Symbol屬性淑翼。

var obj = {
  name:'ConardLi',
  [Symbol('name2')]:'code秘密花園'
}
Object.getOwnPropertyNames(obj); // ["name"]
Object.keys(obj); // ["name"]
for (var i in obj) {
   console.log(i); // name
}
Object.getOwnPropertySymbols(obj) // [Symbol(name)]

Symbol的應(yīng)用場(chǎng)景

下面是幾個(gè)Symbol在程序中的應(yīng)用場(chǎng)景。

應(yīng)用一:防止XSS

在React的ReactElement對(duì)象中品追,有一個(gè)$$typeof屬性玄括,它是一個(gè)Symbol類型的變量:

var REACT_ELEMENT_TYPE =
  (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
  0xeac7;

ReactElement.isValidElement函數(shù)用來判斷一個(gè)React組件是否是有效的,下面是它的具體實(shí)現(xiàn)肉瓦。

ReactElement.isValidElement = function (object) {
  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
};

可見React渲染時(shí)會(huì)把沒有$$typeof標(biāo)識(shí)遭京,以及規(guī)則校驗(yàn)不通過的組件過濾掉。

如果你的服務(wù)器有一個(gè)漏洞泞莉,允許用戶存儲(chǔ)任意JSON對(duì)象哪雕, 而客戶端代碼需要一個(gè)字符串,這可能會(huì)成為一個(gè)問題:

// JSON
let expectedTextButGotJSON = {
  type: 'div',
  props: {
    dangerouslySetInnerHTML: {
      __html: '/* put your exploit here */'
    },
  },
};
let message = { text: expectedTextButGotJSON };
<p>
  {message.text}
</p >

而JSON中不能存儲(chǔ)Symbol類型的變量鲫趁,這就是防止XSS的一種手段斯嚎。

應(yīng)用二:私有屬性

借助Symbol類型的不可枚舉,我們可以在類中模擬私有屬性挨厚,控制變量讀寫:

const privateField = Symbol();
class myClass {
  constructor(){
    this[privateField] = 'ConardLi';
  }
  getField(){
    return this[privateField];
  }
  setField(val){
    this[privateField] = val;
  }
}

應(yīng)用三:防止屬性污染

在某些情況下堡僻,我們可能要為對(duì)象添加一個(gè)屬性,此時(shí)就有可能造成屬性覆蓋疫剃,用Symbol作為對(duì)象屬性可以保證永遠(yuǎn)不會(huì)出現(xiàn)同名屬性钉疫。

例如下面的場(chǎng)景,我們模擬實(shí)現(xiàn)一個(gè)call方法:

Function.prototype.myCall = function (context) {
  if (typeof this !== 'function') {
    return undefined; // 用于防止 Function.prototype.myCall() 直接調(diào)用
  }
  context = context || window;
  const fn = Symbol();
  context[fn] = this;
  const args = [...arguments].slice(1);
  const result = context[fn](...args);
  delete context[fn];
  return result;
}

我們需要在某個(gè)對(duì)象上臨時(shí)調(diào)用一個(gè)方法巢价,又不能造成屬性污染牲阁,Symbol是一個(gè)很好的選擇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壤躲,一起剝皮案震驚了整個(gè)濱河市城菊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碉克,老刑警劉巖役电,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異棉胀,居然都是意外死亡法瑟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門唁奢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霎挟,“玉大人,你說我怎么就攤上這事麻掸∷重玻” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵脊奋,是天一觀的道長(zhǎng)熬北。 經(jīng)常有香客問我,道長(zhǎng)诚隙,這世上最難降的妖魔是什么讶隐? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮久又,結(jié)果婚禮上巫延,老公的妹妹穿的比我還像新娘。我一直安慰自己地消,他們只是感情好炉峰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脉执,像睡著了一般疼阔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上半夷,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天婆廊,我揣著相機(jī)與錄音值桩,去河邊找鬼虱咧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛儿惫,可吹牛的內(nèi)容都是我干的嗦随。 我是一名探鬼主播列荔,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼枚尼!你這毒婦竟也來了贴浙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤署恍,失蹤者是張志新(化名)和其女友劉穎崎溃,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盯质,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡袁串,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年概而,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囱修。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赎瑰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出破镰,到底是詐尸還是另有隱情餐曼,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布鲜漩,位于F島的核電站源譬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏孕似。R本人自食惡果不足惜踩娘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鳞青。 院中可真熱鬧霸饲,春花似錦、人聲如沸臂拓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胶惰。三九已至傻工,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孵滞,已是汗流浹背中捆。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坊饶,地道東北人泄伪。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像匿级,于是被迫代替她去往敵國(guó)和親蟋滴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348