如何用知名Symbol黑掉JavaScript(5種方法)
他們稱之為知名符號 — 盡管大多數(shù)開發(fā)者從未使用過它們,甚至從未聽說過它們。
這是一個(gè)非??岬墓δ?,你可以用它來實(shí)現(xiàn)這樣的魔法:
你將看到我們?nèi)绾问褂弥?Symbol 構(gòu)建這些類來實(shí)現(xiàn)這一點(diǎn)。
它們?nèi)际顷P(guān)于完全定制內(nèi)置操作(如for..of)的正常行為。這就像C++和C#中的運(yùn)算符重載。
它們也都是Symbol類的靜態(tài)方法。
1. Symbol.hasInstance
首先我們有Symbol.hasInstance:用于輕松改變instanceof運(yùn)算符的行為。
通常,instanceof用于檢查一個(gè)變量是否是某個(gè)類的實(shí)例。
就像它應(yīng)該的那樣;相當(dāng)標(biāo)準(zhǔn)的東西。
但是使用Symbol.hasInstance,我們可以完全改變instanceof的工作方式:
現(xiàn)在就instanceof而言,一個(gè)Person不再是Person了。
如果我們不想完全覆蓋它,而是以一種直觀的方式擴(kuò)展它呢?
我們不能在 Symbol 內(nèi)部使用instanceof,因?yàn)槟菚?huì)很快導(dǎo)致無限遞歸:
class Person {
static [Symbol.hasInstance](instance) {
return instance instanceof Person; // 無限遞歸!
}
}
相反,我們將對象的特殊constructor屬性與我們自己的進(jìn)行比較:
如果你剛剛聽說.constructor,這應(yīng)該解釋一切:
2. Symbol.iterator
我們的下一個(gè)黑客技巧是Symbol.iterator,用于完全改變循環(huán)如何以及是否在對象上工作。
還記得這個(gè)嗎:
我們通過Symbol.iterator實(shí)現(xiàn)了這一點(diǎn):
我們再次看到生成器出現(xiàn)。
每當(dāng)我們使用for..of時(shí)。
這在幕后發(fā)生:
因此,通過Symbol.iterator,我們完全改變了for..of對任何List對象的操作:
3. Symbol.toPrimitive
使用Symbol.toPrimitive,我們可以快速從這個(gè):
變成這個(gè):
我們通過覆蓋Symbol.toPrimitive實(shí)現(xiàn)了這一點(diǎn):
現(xiàn)在我們可以在任何使用字符串進(jìn)行插值和連接的地方使用Person對象:
甚至還有一個(gè)hint參數(shù),可以使對象表現(xiàn)得像number、string或其他東西。
4. Symbol.split
天才的知名 Symbol,用于將你的自定義對象轉(zhuǎn)換為字符串分隔符:
5. Symbol.search
就像Symbol.split一樣,將你的自定義對象轉(zhuǎn)換為復(fù)雜的字符串搜索工具:
最后的思考
從循環(huán)到分割再到搜索,知名符號讓我們可以重新定義我們的核心功能,使它們以獨(dú)特和令人愉快的方式運(yùn)行,推動(dòng)了JavaScript可能性的邊界。