鮮為人知的JavaScript功能

By Viral Shah | Nov 26, 2018

原文

js一門很容易入門但是很難精通的語言。我很認(rèn)同這句話。這是因?yàn)閖s是一門古老的語言同時(shí)也是一門很靈活的語言。有著一堆神秘的語法和過時(shí)的功能。我已經(jīng)使用js很多年了,迄今為止,我時(shí)不時(shí)地會(huì)發(fā)現(xiàn)一些我從未知道的隱藏語法或技巧。

whatthejsisthat.jpg

我試圖列出一些鮮為人知的js特性。雖然有一些特性在嚴(yán)格模式下是不能用的,但是它依然是一種不錯(cuò)的js特性。然而,請(qǐng)注意,我不建議你全使用上我介紹的特性。雖然它們很酷,但畢竟是鮮為人知的特性,你的同事可能會(huì)看不懂。

void 操作符

js有一元運(yùn)算符。你可能已經(jīng)見過了,像 void(0) 或者 void0 。它只有一個(gè)目的 - 在右邊評(píng)估表達(dá)式并返回undefined。使用0只是一種慣例。不一定要使用0.它可以是任何有效的表達(dá)式,如

void <expression>

它仍然返回undefined。

voidOperator.png

為什么要這樣子返回undefined,直接返回undefined不好么?看起來這個(gè)特性很多余,不是么?

有趣的事實(shí)

好吧,事實(shí)證明,在ES5之前,你實(shí)際上可以在大多數(shù)瀏覽器中為undefined重新分配值。類似這樣

undefined =“abc”

使用void的話會(huì)始終保持返回正確的undefined。

構(gòu)造函數(shù)的括號(hào)是可選的

對(duì)的,你沒看錯(cuò),當(dāng)調(diào)用構(gòu)造函數(shù)的時(shí)候,我們?cè)陬惷竺婕拥膱A括號(hào)——完全是可選的!??(前提是你不需要傳遞參數(shù))

下面的代碼樣式都被認(rèn)為是有效的JS語法,并且會(huì)給你完全相同的結(jié)果!

constructorBrackets.png

IIFE的括號(hào)可以被跳過

IIFE的語法讓我感覺總是有點(diǎn)奇怪。

IIFE所有的括號(hào)都有什么用?

那些額外的括號(hào)只是為了告訴js解析器,即將到來的代碼是函數(shù)表達(dá)式而不是函數(shù)。知道了這些,來想一想,有很多方法可以跳過這些額外的括號(hào),仍然可以制作有效的IIFE。

IIFEBrackets.png

void操作符告訴解析器這段代碼是函數(shù)表達(dá)式。因此,我們可以省略包著函數(shù)的括號(hào)。你猜怎么著?我們可以使用任何一元運(yùn)算符(void,+ ,!, - 等),這仍然有效。

真酷!

然而,如果你觀察再仔細(xì)點(diǎn),你會(huì)有個(gè)疑問,

一元運(yùn)算符不會(huì)影響IIFE返回的結(jié)果嗎?

好吧,它會(huì)影響結(jié)果。但是有個(gè)好消息,如果你關(guān)心返回的結(jié)果并且把結(jié)果放在某個(gè)變量中,那么你首先不需要額外的括號(hào)。

這就對(duì)了!

IIFEUnary.png

我們添加這些括號(hào)只是為了更好的代碼可讀性。

with 聲明

你知道js有with聲明塊?with一直是js的關(guān)鍵詞。語法如下:

with (object)
   statement 
// for multiple statements add a block
with (object) {
   statement
   statement
   ...
}

with可以對(duì)傳遞過來的對(duì)象進(jìn)行解析,在with 塊里可以直接使用對(duì)象的屬性。

withObject.png

有趣的事實(shí)

with塊看起來很酷對(duì)不對(duì)?甚至比object destructuring還好。

但是,并不是這樣的。

通常不鼓勵(lì)使用with語句,因?yàn)樗驯粭売谩?在嚴(yán)格模式下完全禁止。 事實(shí)證明,with塊會(huì)增加語言中的一些性能和安全性問題。Bummer

構(gòu)造函數(shù)

function語句并不是定義新函數(shù)的唯一方法;你可以使用【Function()】這個(gè)構(gòu)造函數(shù)和new運(yùn)算符動(dòng)態(tài)定義函數(shù)。

functionConstruction.png

構(gòu)造函數(shù)的最后一個(gè)參數(shù)是字符串化代碼,就是你寫的函數(shù)。其他參數(shù)是該函數(shù)的參數(shù)。

有趣的事實(shí)

在js,F(xiàn)unction構(gòu)造函數(shù)是所有構(gòu)造函數(shù)的構(gòu)造函數(shù)。也包括Object的構(gòu)造函數(shù)。并且Function構(gòu)造函數(shù)的構(gòu)造函數(shù)就是它自身。因此,調(diào)用object.constructor.constructor...足夠多次后,在js中,最終會(huì)在任何對(duì)象返回Function構(gòu)造函數(shù)。

Function 的屬性

我們知道在js中,F(xiàn)unctions是首個(gè)對(duì)象。因此,沒有人能阻止我們?cè)贔unction對(duì)象上添加自己的屬性。這是可以的,但是很少會(huì)這樣做。

那有什么場(chǎng)景會(huì)應(yīng)用到呢?

有一些很好的用例。例如,

讓Functions可配置化

我們有個(gè)greet函數(shù)。我們想要讓我們的函數(shù)在不同的環(huán)境下打印不同語言的問候語。這個(gè)環(huán)境是可以配置的。我們可以在某處維護(hù)個(gè)全局環(huán)境變量,或者使用上文所說的添加自定義屬性

ConfigurableFunctions.png

Function的靜態(tài)變量

另一個(gè)相似的例子。假設(shè)你想要實(shí)現(xiàn)一個(gè)生成一系列有序數(shù)字的數(shù)字生成器。通常來說,你會(huì)用Class或者IIFE,在里面維護(hù)一個(gè)計(jì)數(shù)變量,然后輸出有序的值。這樣我們就可以限制對(duì)計(jì)數(shù)器的訪問,并避免使用額外的變量來污染全局空間。

但是,如果我們希望靈活地讀取甚至修改計(jì)數(shù)器并且不污染全局空間呢?

好吧,我們?nèi)匀豢梢詣?chuàng)建一個(gè)Class,帶有一個(gè)計(jì)數(shù)器變量和一些額外的方法來讀取它; 或者我們可以懶一點(diǎn),只需在函數(shù)上使用屬性。

FunctionWithStaticVariables.png

現(xiàn)在是中場(chǎng)休息時(shí)間,我們等你回來。如果你想接著繼續(xù),你是一個(gè)勇敢的戰(zhàn)士,我向你致敬。

繼續(xù)吧

Arguments屬性

我相信大多數(shù)人都知道函數(shù)中的參數(shù)對(duì)象。 它是一個(gè)像對(duì)象一樣的數(shù)組(譯者:emmm),在所有函數(shù)中都能訪問到。它具有在調(diào)用函數(shù)時(shí)傳遞的參數(shù)列表,也有其他一些有趣的屬性。

  • arguments.callee:指向當(dāng)前調(diào)用函數(shù)
  • arguments.callee.caller:指向當(dāng)前被調(diào)函數(shù)的調(diào)用者。
ArgumentsProperties.png

注意:雖然ES5禁止在嚴(yán)格模式下使用callee和caller,但在許多編譯庫中仍然常見。 所以,值得學(xué)習(xí)它們。

標(biāo)記模版字面量

除非你是井底之蛙,你一定聽說過模版字面量。模版字面量時(shí)es6的一個(gè)很酷的補(bǔ)充。然而,你聽說過Tagged模版字面量么(Tagged Template Literals)?

TaggedTemplateLiterals.png

Tagged模板字面量允許您通過向模板字面量添加自定義標(biāo)記來更好地控制將模板字面量解析為字符串。Tagged只是一個(gè)獲取字符串模板解析后的所有字符串和值的數(shù)組的解析器函數(shù)。Tagged函數(shù)最終返回字符串。

在下面的示例中,我們的自定義標(biāo)記 - highlight,解釋模板文字的值,并使用

<mark>

元素將解釋的值包裝在結(jié)果字符串中,以突出顯示。

Tagged.png

Getter & Setter

在大多數(shù)情況下,js對(duì)象時(shí)很簡(jiǎn)單的。比如說有一個(gè)對(duì)象叫user,我們嘗試使用user.age來讀取age屬性時(shí),如果有定義并賦值了,就有返回。如果沒有,就返回undefined。簡(jiǎn)單。

但是,它不一定非常簡(jiǎn)單。 JavaScript對(duì)象具有Getters和Setter的概念。 我們可以編寫自定義的Getter函數(shù)來返回我們想要的任何內(nèi)容,而不是直接返回對(duì)象上的值。 設(shè)置值也是一樣的。

這使我們可以在獲取或設(shè)置屬性時(shí)可以靈活的創(chuàng)造虛擬屬性、驗(yàn)證屬性。

GettersSetters.png

Getters和Setters不是es5的特性,它們是一直都存在的特性。es5只是添加了語法糖。

逗號(hào)操作符

JavaScript有一個(gè)逗號(hào)運(yùn)算符。 它允許我們?cè)谝恍兄芯帉懹啥禾?hào)分隔的多個(gè)表達(dá)式,并返回最后一個(gè)表達(dá)式的結(jié)果

// syntax
let result = expression1, expression2,... expressionN

來看看上面的例子,這里將會(huì)解析所有的表達(dá)式,并把result變量賦予expressionN返回的值。

你可能在循環(huán)里面使用過了

for (var a = 0, b = 10; a <= 10; a++, b--)

它可以幫助我們把語句寫在一行

function getNextValue() {
    return counter++, console.log(counter), counter
}

或者寫lamda表達(dá)式

const getSquare = x => (console.log (x), x * x)

+ 加操作符

想要知道如何便捷地把字符串轉(zhuǎn)換成number?

只要在字符串前面加個(gè)+號(hào)。

Plus運(yùn)算符也適用于負(fù),八進(jìn)制,十六進(jìn)制,指數(shù)值。 更重要的是,它甚至可以將Date或Moment.js對(duì)象轉(zhuǎn)換為時(shí)間戳!

PlusOperator.png

!! Bang Bang 操作符

好的,嚴(yán)格來講,它不是一個(gè)單獨(dú)的JavaScript運(yùn)算符。 它只是兩次使用的JavaScript否定運(yùn)算符。

但是Bang Bang聽起來很酷!Bang Bang是一個(gè)可以講任何表達(dá)式轉(zhuǎn)換成布爾值的方法。

如果表達(dá)式是一個(gè)true,則返回true;否則返回false。

BangBangOperator.png

~ 位運(yùn)算作符

來看一個(gè)沒人關(guān)注的位運(yùn)算操作符。我們什么時(shí)候用它呢?

好吧,有個(gè)日常用例。

當(dāng)與數(shù)字一起使用時(shí),Tilde運(yùn)算符有效,像這樣

~N => -(N + 1)。

僅當(dāng)N == -1時(shí),此表達(dá)式的計(jì)算結(jié)果為“0”

我們可以通過在indexOf(...)函數(shù)前面放置?來進(jìn)行布爾檢查是否有一項(xiàng)存在。String或Array中都可以用這個(gè)。

TildeOperator.png

注意:ES6和ES7分別在String&Array中添加了一個(gè)新的.includes()方法。當(dāng)然,它比位運(yùn)算運(yùn)算符更清晰,以檢查項(xiàng)目是否存在于Array或String中。

標(biāo)簽語句

js具有標(biāo)簽語句的概念。它允許我們?cè)趈s中命名循環(huán)和塊。然后,我們可以使用這些標(biāo)簽在使用break或continue時(shí)使用。

帶標(biāo)簽的語句在嵌套循環(huán)中特別方便。但是我們也可以使用它們來簡(jiǎn)單地將代碼組織成塊或創(chuàng)建一個(gè)可退出的塊

LabelledStatements.png

注意:不像其他的語言,js沒有g(shù)oto語句。因此,我們只能使用labels來搭配break和continue使用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容