JS 中 IIFE 與分號的最酷寫法
IIFE
是在 JS 中為了彌補沒有 block scope 而出現的寫法。
一般人習慣使用括號做為前置,
但其實括號出現在行首䆟易被
ASI
誤判為函數呼叫,使用上最佳寫法應為
!function(){}()
或 void function(){}()
。
函數表達式
JS 中存在函數表達式 (expression) 與函數宣告,兩者語法很不幸的相同。 當函數表達式置於行首時, (其實應該說是一個陳述 (statement) 的開頭, 不一定不能是行首。) 就會被解釋為函數宣告。
所以使用 iife 時,唯一要注意就是 不要把 iife 放在句首即可; 其它你愛怎麼宣告,就怎麼宣告。
function foo() {} // declaretion
(function foo() {}) // expression, value is function.
!function bar() {}()
// iife, value is true,
// because function return undefined,
// !undefined == true
分號自動插入判斷
但身為懶惰的程式設計師, 當然可以不寫分號 ; 況且 feature 就是拿來用的, 不然 JS 幹麻設計分號自動插入的功能? 所以就簡單研究一下怎麼樣不寫分號會造成問題。
js 在句尾會自動判斷 statement 結尾, 只要 可能還沒結束 就會被當成沒結束, 就不會插入分號。
括號呼叫函數
當下一行以 (
開頭,會被當成函數呼叫。
doc = createDocument(document)
(a+b) / c
因為 doc = createDocument(document)
也是一個表達式,返回 doc。
所以 doc 就會被當成函數以參數 a+b
呼叫,
然後一般就會丟出一個 Type error,
因為 doc 一般不會是函數。
(doc = createDocument(document))(a+b) / c
中括號存取陣列
當下一行以 [
開頭,會被當成陣列,
所以也不要用 [
開頭
doc = createDocument(document)
[1,2,3].forEach(doc.showIndex)
這點 js 真得有點笨,
[1,2,3]
怎麼看都是陣列字面量,
但 JS 就會當成存取 doc 的屬性,
然後丟出語法錯誤,因為存取屬性不能有逗號。
(但實際試過,好像會只存取最後一個,不會丟語法錯誤。)
或因為 doc 返回了 undefined 或 null
丟 type error 或 reference error。
standerJS 的建議是不要把陣列字面量擺行首, 看要先前置分號或先賦值。
statement;
[1,2,3].forEach(doc.showIndex)
// not good.
;[1,2,3].forEach(doc.showIndex)
// good.
var list = [1,2,3]
list.forEach(doc.showIndex)
// better
一元算符
有沒有發現,我們用來防止誤認函數表達式的都是一元算符?
但有些一元算符因為也可以被當二元算符,而容易出錯。
像 +
可以是把數字加一個正號,
(也就是什麼也不做。)或是把兩個數相加。
如果有上一個 statement,就會加在一起。
而括號可以是單純一元算符,(對內求值。)
或是將內部做為前一個表達式的參數呼叫函數。
+(-3) // expression, return -3.
var i = 1
+(-3) // ops, i = -2 now.
所以我們需要一個不會被當成二元算符的一元算符,
我的名單有 !
、 ~
、 void
。
!
很好理解,就是 bool 反轉,
僅次於 (function(){})()
的寫法就是 !function(){}()
。
而 ~
是 bit 級 not 算符,
至於它對函數的運算結果,反正不是我們關心的。
最強寫法
最後一個 void
是我認為最強的寫法。
void 是一個較少人知道的算符,
她接受任何參數,然後返回 undefined。
所以你可以寫 void function(){}()
,
是不是有 C 的感覺?是不是很帥!
因為 undefined 不是字面量,
她是一個 全域變數 ,
在瀏覽器中是掛在 window 下面。
你可以在除了全域外的任何 scope 宣告
var undefined = true
,
然後你就看不到 undefined 了ㄎㄎ
所以才有了 void 這個算符,
不管你有沒有對 undefined 動手腳,
不管你被包了幾層 scope,
只要對 void 隨便丟一個參數,都會返回 undefined。
一般的寫法是 void 0
,但其實右邊放什麼都沒差。