6. Symbol和Symbol屬性

在ES6之前,語(yǔ)言包含5中類型骡湖。字符串贱纠,數(shù)字,布爾响蕴,undefined, null.
ES6之后谆焊,包含了新類型Symbol類型。人們一般通過(guò)屬性名來(lái)訪問(wèn)屬性浦夷。無(wú)論屬性名是什么組成辖试,全部由字符串類型來(lái)進(jìn)行訪問(wèn)。私有名稱是為了讓開發(fā)者創(chuàng)建非字符串的名稱军拟。

1. 創(chuàng)建Symbol

除了Symbol剃执,都有各自字面量的形式⌒赶ⅲ可以通過(guò)全局Symbol創(chuàng)建Symbol

// firstName相當(dāng)于一個(gè)變量名稱肾档,不會(huì)轉(zhuǎn)化的變量名稱
let person = {};
let firstName = Symbol(); // firstName就是一個(gè)值,獨(dú)一無(wú)二的值辫继。
person[firstName] = "Nicholas";
console.log(person[firstName])
// 在以前的書寫中
let secondName = 'sN'; 
person[secondName] = "Nicholas";
console.log(person[secondName]) // 但是這里會(huì)轉(zhuǎn)化為person.sN

Symbole是原始值怒见。使用new Symbol會(huì)拋出錯(cuò)誤。
Symbole可以接受一個(gè)描述文本姑宽。但是這段描述不會(huì)用于屬性訪問(wèn)遣耍。但是建意我們?cè)趧?chuàng)建Symbole對(duì)象增加描述。

// firstName相當(dāng)于一個(gè)變量名稱炮车,不會(huì)轉(zhuǎn)化的變量名稱
let person = {};
let firstName = Symbol('first name'); // firstName就是一個(gè)值舵变,獨(dú)一無(wú)二的值。
person[firstName] = "Nicholas";
console.log(person[firstName]) // "Nicholas"
console.log('first name' in person) //  false
console.log(firstName) // Symbol('first name')

Symbol的描述會(huì)被添加在[[Description]]屬性中瘦穆。只有當(dāng)調(diào)用Symbol的toString方法纪隙,描述才會(huì)被打印到日志中。

notice: Symbol是原始值扛或,可以進(jìn)行typeof操作符绵咱,返回Symbol類型。我們可以使用typeof查看瀏覽器對(duì)Symbol的支持情況

2. Symbol的使用方法

所有使用計(jì)算屬性名的地方都可以使用Symbol熙兔。Symbol可以適用于計(jì)算對(duì)象字面量屬性名悲伶、Object.defineProperties()方法中使用

let firstName = Symbol('first name'); 
let person = {[firstName]: 'Nicholas'};
Object.defineProperties(person, firstName, {writeable: false}) // 屬性設(shè)置為只讀
let lastName = Symbol('last name'); 
Object.defineProperties(person, {lastName: {value: 'Zakas', writeable: false}})
console.log(person[firstName], person[lastName]); // Nicholas Zakas

3. Symbol共享體系

我們希望在不同的代碼片段中共享一個(gè)Symbol。這時(shí)候住涉,ES6中提供了隨時(shí)可以訪問(wèn)的Symbol注冊(cè)表麸锉。如果想建立共享的Symbol,要使用Symbol.for()方法舆声。只接受一個(gè)參數(shù)淮椰,也就是即將創(chuàng)建的symbole的字符串標(biāo)識(shí)符。或者是描述

let uid = Symbol.for(uid);
let obj = {};
obj[uid] = "12345";
console.log(obj[uid]); // "12345"
console.log(uid); // Symbol(uid)

Symbol.for();會(huì)在全局的Symbol注冊(cè)表中搜索鍵為uid的Symbol主穗。如果存在,則返回值毙芜,不存在忽媒,則進(jìn)行注冊(cè),并且返回新的Symbol腋粥。
eg:

let uid = Symbol.for(uid);
let obj = {
  [uid]: "12345";
};
console.log(obj[uid]); // "12345"

let uid2 = Symbol.for(uid);
console.log(uid === uid2); // "12345"
console.log(obj[uid]); // "12345"
console.log(uid2); // Symbol(uid)

還可以使用Symbol.keyFor()在Symbol全局注冊(cè)表中檢索與Symbol有關(guān)的鍵

let uid = Symbol.for(uid);
console.log(Symbol.keyFor(uid)); // uid
let uid2 = Symbol.for(uid);
console.log(Symbol.keyFor(uid2)); // uid
let uid3 = Symbol(uid);
console.log(Symbol.keyFor(uid3)); // undefined 因?yàn)闆](méi)有在全局的注冊(cè)表中注冊(cè)晦雨。所以不能搜到。

4. Symbol與類型強(qiáng)轉(zhuǎn)關(guān)系

因?yàn)槠渌禌](méi)有與Symbol邏輯等價(jià)的值隘冲,因?yàn)镾ymbol使用不太方便闹瞧。并且Symbol不能墻磚轉(zhuǎn)化為字符串和數(shù)字類型,可能會(huì)錯(cuò)誤操作對(duì)象屬性展辞,導(dǎo)致結(jié)果不一致奥邮。

let uid = Symbol('uid'), desc = String(uid);
console.log(uid); // Symbol('uid') 但是他是string類型的
// 但是不能直接與字符串拼接會(huì)報(bào)錯(cuò)
console.log(uid + ''); // 報(bào)錯(cuò)
// 不能強(qiáng)制轉(zhuǎn)化為數(shù)字類型
console.log(uid/1); // 報(bào)錯(cuò)
// 除了邏輯操作符 為true

5. Symbol屬性檢索

Symbol.keyFor()和Object.getOwnPropotyNames()都可以檢索對(duì)象中所有的屬性名。Symbol.keyFor()返回的是可枚舉的屬性名罗珍。Object.getOwnPropotyNames()返回所有屬性名洽腺,一律返回。這兩個(gè)都不可支持Symbol屬性覆旱。Object.getOwnPropotySymbols()放大來(lái)檢索對(duì)象中的Symbol屬性蘸朋。

let uid = Symbol.for(uid);
let obj = {
 [uid]: "12345";
};
let symbols = Object.getOwnPropotySymbols(obj);
symbols.length // 1
symbols[0] // Symbol(uid)
obj[symbols[0]] //  "12345"
// 對(duì)象中可以繼承Symbol屬性。

6. 通過(guò)well-konwn Symbol暴露內(nèi)部操作

6.1 Symbol.hasInstance方法

每個(gè)函數(shù)中都有Symbol.hasInstance方法扣唱,用于確定對(duì)象是否為函數(shù)實(shí)例藕坯。在Function.prototypes中定義,所有的函數(shù)都繼承了instance的默認(rèn)行為噪沙。為了確保Symbol.hasInstance不會(huì)被意外重寫炼彪,該方法定義為不可寫,不可配置并且不可枚舉曲聂。Symbol.hasInstance只接受被一個(gè)參數(shù)霹购,要檢查的值。

obj instance Array;
// 等價(jià)于
Array[Symbol.hasInstance](obj) // Symbol.hasInstance是個(gè)屬性朋腋?!!!就像Symbol(123)么揍障???
function MyObject() {
  // 空函數(shù)
}
object.definePropoty(MyObject, Symbol.hasInstance, {
  value: function(v) {
    return false;
  }
})

let obj = new MyObject();
obj.instanceof MyObject // false

建議不要改寫。

6.2 Symbol.isConcatSpreadable屬性

concat使用方法肛鹏。

let color1 = ['red', 'green'],
let color2 = color1.concat(['blue', 'black']);
let color2 = color1.concat(['yellow'], 'purple');
color2 // ['red', 'green', 'blue', 'black', 'yellow', 'purple']

按照道理复唤,會(huì)直接將參數(shù)一個(gè)一個(gè)的增加在新的數(shù)組中,為什么數(shù)組會(huì)展開呢?因?yàn)樵趈s中,凡是傳入了數(shù)組參數(shù),會(huì)自動(dòng)將他們分割為獨(dú)立元素。Symbol.isConcatSpreadable屬性是一個(gè)Bool值彼绷。true表示對(duì)象有l(wèi)ength屬性,和數(shù)字鍵,他的數(shù)字值型屬性值筹吐,會(huì)獨(dú)立添加到concat調(diào)用結(jié)果中。Symbol這個(gè)屬性默認(rèn)不會(huì)出現(xiàn)在標(biāo)準(zhǔn)對(duì)象中洋侨,是可選屬性舍扰。增加對(duì)象的concat()方法調(diào)用。

let collection = {
  0: 'Hello',
  1: 'world',
  length: 2,
  Symbol.isConcatSpreadable: true
}

let msg = ['Hi'].concat(collection);
msg // ['Hi', 'Hello', 'world']
6.3 Symbol.match希坚、Symbol.replace边苹、Symbol.search、Symbol.split屬性

接受正則表達(dá)式作為參數(shù)
.match(regex)判斷正則匹配
.replace(regex, replacement)正則表達(dá)式匹配結(jié)果
.search(regex)進(jìn)行定位
.split(regex)字符串分割
在es6之前是不能對(duì)這幾個(gè)方法進(jìn)行自定義裁僧,進(jìn)行字符串匹配个束。ES6之后用symbol屬性,將regex的元素特性完全暴露聊疲。
Symbol.match茬底、Symbol.replace、Symbol.search获洲、Symbol.split屬性表示match(), replace(), search(), split()方法中的第一個(gè)參數(shù)應(yīng)該調(diào)用的正則表達(dá)式參數(shù)的方法阱表。他們被定義在Regex.prototype中。

let regex2 = {
  [Symbol.match]: function (value) {
    return false;
  }
};
'hello'.match(regex2)
6.4 Symbol.toPrimitive方法

js經(jīng)常做隱式轉(zhuǎn)換贡珊。比如 == 會(huì)轉(zhuǎn)化為基本類型最爬。但是到底轉(zhuǎn)戶為什么基本類型,在之前是內(nèi)部操作飞崖,但是es6之后通過(guò)Symbol.toPrimitive暴露出來(lái)了烂叔,并且可以對(duì)其修改。
Symbol.toPrimitive定義在所有常規(guī)類型的原型上,規(guī)定了轉(zhuǎn)化規(guī)則闸溃。當(dāng)轉(zhuǎn)化是會(huì)進(jìn)行調(diào)用,并傳入提示性參數(shù)坯苹。這個(gè)參數(shù)有3種可能逢防。number string default

number :調(diào)用valueof()方法叶沛,返回基本類型,返回它忘朝。否則調(diào)用toString()方法返回灰署,否則拋出錯(cuò)誤
string :調(diào)用toString()方法,返回基本類型局嘁,返回它溉箕。否則調(diào)用valueof()方法返回,否則拋出錯(cuò)誤
default : 多數(shù)在== + 運(yùn)算符或者傳遞單一參數(shù)給date構(gòu)造器被使用悦昵。

多數(shù)情況下肴茄,常規(guī)對(duì)象等價(jià)于數(shù)值模式?但指?寡痰??Date類型除外棋凳,使用string模式

function Templerature(value) {
  this.value = value;
}
Templerature.prototype[Symbol.toPrimitive] = function(hint) {
  switch (hint) {
    case 'string': 
      return this.value+'!'
  }
}
let tmp = new Templerature(32);
String(tmp)
"32!"
6.5 Symbol.toStringTag屬性
function isArray(value) {
 return Object.prototype.toString.call(value) === "[object Array]";
}
console.log(isArray([])); // true

ES6通過(guò) Symbol.toStringTag 定義了 Object.prototype.toString.call() 被調(diào)用時(shí)應(yīng)當(dāng)返回什么值拦坠。對(duì)于數(shù)組來(lái)說(shuō),在Symbol.toStringTag 屬性中存儲(chǔ)了 "Array" 值剩岳,于是該函數(shù)的返回值也就是 "Array" 贞滨。

function Person(name) {
  this.name = name;
}
Person.prototype[Symbol.toStringTag] = "Person";

let me = new Person("Nicholas");
console.log(me.toString()); // "[object Person]"
console.log(Object.prototype.toString.call(me)); //  "[object Person]"

Symbol.toStringTag 的返回值在調(diào)用 me.toString() 的時(shí)候也會(huì)被使用。

function Person(name) {
  this.name = name;
}
Person.prototype[Symbol.toStringTag] = "Person";
Person.prototype.toString = function() {
return this.name;
};

let me = new Person("Nicholas");
console.log(me.toString()); // "Nicholas"
console.log(Object.prototype.toString.call(me)); //  "[object Person]"
6.6 Symbol.unscopables屬性

with語(yǔ)句的支持卢肃。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疲迂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子莫湘,更是在濱河造成了極大的恐慌尤蒿,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幅垮,死亡現(xiàn)場(chǎng)離奇詭異腰池,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)忙芒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門示弓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人呵萨,你說(shuō)我怎么就攤上這事奏属。” “怎么了潮峦?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵囱皿,是天一觀的道長(zhǎng)勇婴。 經(jīng)常有香客問(wèn)我,道長(zhǎng)嘱腥,這世上最難降的妖魔是什么耕渴? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮齿兔,結(jié)果婚禮上橱脸,老公的妹妹穿的比我還像新娘。我一直安慰自己分苇,他們只是感情好添诉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著医寿,像睡著了一般吻商。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上糟红,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音乌叶,去河邊找鬼盆偿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛准浴,可吹牛的內(nèi)容都是我干的事扭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乐横,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼求橄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起葡公,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤罐农,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后催什,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涵亏,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年蒲凶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了气筋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡旋圆,死狀恐怖宠默,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灵巧,我是刑警寧澤搀矫,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布抹沪,位于F島的核電站,受9級(jí)特大地震影響艾君,放射性物質(zhì)發(fā)生泄漏采够。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一冰垄、第九天 我趴在偏房一處隱蔽的房頂上張望蹬癌。 院中可真熱鬧,春花似錦虹茶、人聲如沸逝薪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)董济。三九已至,卻和暖如春要门,著一層夾襖步出監(jiān)牢的瞬間虏肾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工欢搜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留封豪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓炒瘟,卻偏偏與公主長(zhǎng)得像吹埠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疮装,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 原始類型:Symbol缘琅,用于創(chuàng)建必須通過(guò)Symbol才能引用的屬性,提供了一些私有性和不易覆蓋的特性廓推。 1刷袍、創(chuàng)建S...
    Zip_Wang閱讀 907評(píng)論 0 50
  • 回憶一下JS中的原始類型:字符串型、數(shù)字型樊展、布爾型做个、null和undefined。 ES6中引入了第6種原始類型:...
    ___Jing___閱讀 8,663評(píng)論 2 10
  • 原創(chuàng)文章&經(jīng)驗(yàn)總結(jié)&從校招到A廠一路陽(yáng)光一路滄桑 詳情請(qǐng)戳www.codercc.com 主要知識(shí)點(diǎn):創(chuàng)建符號(hào)值滚局、...
    你聽(tīng)___閱讀 906評(píng)論 0 1
  • 概述 ES5 的對(duì)象屬性名都是字符串居暖,這容易造成屬性名的沖突。比如藤肢,你使用了一個(gè)他人提供的對(duì)象太闺,但又想為這個(gè)對(duì)象添...
    米諾zuo閱讀 332評(píng)論 0 0
  • 本人是android開發(fā)的,由于最近React Native的火熱,再加上自己完全不懂JS的語(yǔ)法,俗話說(shuō)的好"落后...
    Bui_vlee閱讀 283評(píng)論 0 0