原文javascript
js一門很容易入門可是很難精通的語言。我很認同這句話。這是由於js是一門古老的語言同時也是一門很靈活的語言。有着一堆神祕的語法和過期的功能。我已經使用js不少年了,迄今爲止,我時不時地會發現一些我從未知道的隱藏語法或技巧。java
我試圖列出一些不爲人知的js特性。雖然有一些特性在嚴格模式下是不能用的,可是它依然是一種不錯的js特性。然而,請注意,我不建議你全使用上我介紹的特性。雖然它們很酷,但畢竟是不爲人知的特性,你的同事可能會看不懂。es6
js有一元運算符。你可能已經見過了,像 void(0) 或者 void0 。它只有一個目的 - 在右邊評估表達式並返回undefined。使用0只是一種慣例。不必定要使用0.它能夠是任何有效的表達式,如express
void <expression>
複製代碼
它仍然返回undefined。數組
爲何要這樣子返回undefined,直接返回undefined很差麼?看起來這個特性不少餘,不是麼?瀏覽器
好吧,事實證實,在ES5以前,你實際上能夠在大多數瀏覽器中爲undefined從新分配值。相似這樣安全
undefined =「abc」
複製代碼
使用void的話會始終保持返回正確的undefined。函數
對的,你沒看錯,當調用構造函數的時候,咱們在類名後面加的圓括號——徹底是可選的!😮(前提是你不須要傳遞參數)性能
下面的代碼樣式都被認爲是有效的JS語法,而且會給你徹底相同的結果!學習
IIFE的語法讓我感受老是有點奇怪。
IIFE全部的括號都有什麼用?
那些額外的括號只是爲了告訴js解析器,即將到來的代碼是函數表達式而不是函數。知道了這些,來想想,有不少方法能夠跳過這些額外的括號,仍然能夠製做有效的IIFE。
void操做符告訴解析器這段代碼是函數表達式。所以,咱們能夠省略包着函數的括號。你猜怎麼着?咱們可使用任何一元運算符(void,+ ,!, - 等),這仍然有效。
真酷!
然而,若是你觀察再仔細點,你會有個疑問,
一元運算符不會影響IIFE返回的結果嗎?
好吧,它會影響結果。可是有個好消息,若是你關心返回的結果而且把結果放在某個變量中,那麼你首先不須要額外的括號。
這就對了!
咱們添加這些括號只是爲了更好的代碼可讀性。
你知道js有with聲明塊?with一直是js的關鍵詞。語法以下:
with (object)
statement
// for multiple statements add a block
with (object) {
statement
statement
...
}
複製代碼
with能夠對傳遞過來的對象進行解析,在with 塊裏能夠直接使用對象的屬性。
with塊看起來很酷對不對?甚至比object destructuring還好。
可是,並非這樣的。
一般不鼓勵使用with語句,由於它已被棄用。 在嚴格模式下徹底禁止。 事實證實,with塊會增長語言中的一些性能和安全性問題。Bummer
function語句並非定義新函數的惟一方法;你可使用【Function()】這個構造函數和new運算符動態定義函數。
構造函數的最後一個參數是字符串化代碼,就是你寫的函數。其餘參數是該函數的參數。
在js,Function構造函數是全部構造函數的構造函數。也包括Object的構造函數。而且Function構造函數的構造函數就是它自身。所以,調用object.constructor.constructor...足夠屢次後,在js中,最終會在任何對象返回Function構造函數。
咱們知道在js中,Functions是首個對象。所以,沒有人能阻止咱們在Function對象上添加本身的屬性。這是能夠的,可是不多會這樣作。
那有什麼場景會應用到呢?
有一些很好的用例。例如,
讓Functions可配置化
咱們有個greet函數。咱們想要讓咱們的函數在不一樣的環境下打印不一樣語言的問候語。這個環境是能夠配置的。咱們能夠在某處維護個全局環境變量,或者使用上文所說的添加自定義屬性
另外一個類似的例子。假設你想要實現一個生成一系列有序數字的數字生成器。一般來講,你會用Class或者IIFE,在裏面維護一個計數變量,而後輸出有序的值。這樣咱們就能夠限制對計數器的訪問,並避免使用額外的變量來污染全局空間。
可是,若是咱們但願靈活地讀取甚至修改計數器而且不污染全局空間呢?
好吧,咱們仍然能夠建立一個Class,帶有一個計數器變量和一些額外的方法來讀取它; 或者咱們能夠懶一點,只需在函數上使用屬性。
如今是中場休息時間,咱們等你回來。若是你想接着繼續,你是一個勇敢的戰士,我向你致敬。
繼續吧
我相信大多數人都知道函數中的參數對象。 它是一個像對象同樣的數組(譯者:emmm),在全部函數中都能訪問到。它具備在調用函數時傳遞的參數列表,也有其餘一些有趣的屬性。
注意:雖然ES5禁止在嚴格模式下使用callee和caller,但在許多編譯庫中仍然常見。 因此,值得學習它們。
除非你是井底之蛙,你必定據說過模版字面量。模版字面量時es6的一個很酷的補充。然而,你據說過Tagged模版字面量麼(Tagged Template Literals)?
Tagged模板字面量容許您經過向模板字面量添加自定義標記來更好地控制將模板字面量解析爲字符串。Tagged只是一個獲取字符串模板解析後的全部字符串和值的數組的解析器函數。Tagged函數最終返回字符串。
在下面的示例中,咱們的自定義標記 - highlight,解釋模板文字的值,並使用
<mark>
複製代碼
元素將解釋的值包裝在結果字符串中,以突出顯示。
在大多數狀況下,js對象時很簡單的。好比說有一個對象叫user,咱們嘗試使用user.age來讀取age屬性時,若是有定義並賦值了,就有返回。若是沒有,就返回undefined。簡單。
可是,它不必定很是簡單。 JavaScript對象具備Getters和Setter的概念。 咱們能夠編寫自定義的Getter函數來返回咱們想要的任何內容,而不是直接返回對象上的值。 設置值也是同樣的。
這使咱們能夠在獲取或設置屬性時能夠靈活的創造虛擬屬性、驗證屬性。
Getters和Setters不是es5的特性,它們是一直都存在的特性。es5只是添加了語法糖。
JavaScript有一個逗號運算符。 它容許咱們在一行中編寫由逗號分隔的多個表達式,並返回最後一個表達式的結果
// syntax
let result = expression1, expression2,... expressionN
複製代碼
來看看上面的例子,這裏將會解析全部的表達式,並把result變量賦予expressionN返回的值。
你可能在循環裏面使用過了
for (var a = 0, b = 10; a <= 10; a++, b--)
複製代碼
它能夠幫助咱們把語句寫在一行
function getNextValue() {
return counter++, console.log(counter), counter
}
複製代碼
或者寫lamda表達式
const getSquare = x => (console.log (x), x * x)
複製代碼
想要知道如何便捷地把字符串轉換成number?
只要在字符串前面加個+號。
Plus運算符也適用於負,八進制,十六進制,指數值。 更重要的是,它甚至能夠將Date或Moment.js對象轉換爲時間戳!
好的,嚴格來說,它不是一個單獨的JavaScript運算符。 它只是兩次使用的JavaScript否認運算符。
可是Bang Bang聽起來很酷!Bang Bang是一個能夠講任何表達式轉換成布爾值的方法。
若是表達式是一個true,則返回true;不然返回false。
來看一個沒人關注的位運算操做符。咱們何時用它呢?
好吧,有個平常用例。
當與數字一塊兒使用時,Tilde運算符有效,像這樣
~N => -(N + 1)。
複製代碼
僅當N == -1時,此表達式的計算結果爲「0」
咱們能夠經過在indexOf(...)函數前面放置〜來進行布爾檢查是否有一項存在。String或Array中均可以用這個。
注意:ES6和ES7分別在String&Array中添加了一個新的.includes()方法。固然,它比位運算運算符更清晰,以檢查項目是否存在於Array或String中。
js具備標籤語句的概念。它容許咱們在js中命名循環和塊。而後,咱們可使用這些標籤在使用break或continue時使用。
帶標籤的語句在嵌套循環中特別方便。可是咱們也可使用它們來簡單地將代碼組織成塊或建立一個可退出的塊
注意:不像其餘的語言,js沒有goto語句。所以,咱們只能使用labels來搭配break和continue使用。