大綱:
- Function Expression
- Naming Function Expression
- Arrow Function
- Function Types Hierarchy (summarize)
之前 compilation phase 時, 我們提到 function 的宣告 會有一個 identifier,然後我們給他一個有顏色的小球。
那麼,思考以下例子。
function teacher(){ return 'Kyle'; }
var myTeacher = function anotherTeacher(){
console.log(anotherTeacher)
}
console.log(teacher);
console.log(myTeacher);
console.log(anotherTeacher);
按照我們之前給球的邏輯:
compilation phase
line 1 : teacher 紅色
line 3 ... 好像有點有趣。
在 compilation 階段,只會執行 declaration
,
然而,line 3 後面的 function anotherTeacher(){...} 是 Expression
,
代表要等到 run time 才會執行,
也因為不是 declaration,所以你如果輸入 line 9 得 console.log(anotherTeacher)
會得到 ReferenceError: anotherTeacher is not defined
。
compilation phase
line 3 : myTeacher 紅色
line 3 : anotherTeacher, Expression 不會執行
{} 的 function 內部是 藍色(不是 global scope)
line 3 的 function anotherTeacher,是藍色小球 (local lexical scope)
這也就是為什麼
line 4
console 不會有 Error (因為是local lexical scope
)。
但是一樣的 code ,line 9
因為global 沒有宣告
,所以會 ReferenceError
不是幹話,就是
有名字的
Function Expression
你看~ line 5
真的有名字吧。
為什麼是 Function Expression ?
因為不是 Function Declaration ,Function Declaration 一定是關鍵字
function
開始。
有沒有開始覺得和 LHS, RHS 的敘述方式很像了?
named
function expression 和 anonymous
function expression如果 function expression 沒有命名,那就沒有 lexical self-reference.
Kyle Simpson 說他 100% 使用
named
function expression ,
並給你3個
理由。
debuggable
stack traces
避免以下情形:
Kyle 一直強調,寫 code 是優先給人看,而且工程師透過 code 來
溝通
(communicate more clearly your intent.)
所以,避免誤解或混淆,最好的方法就是把 function 命名。
有時候 Kyle 想不到名字,會暫時性命名做 TODO
,因為他 commit 前會檢查所有 TODO,
這時候回來看 funtion 的目的就會比較容易命名。
如果你真的想不到名字:
每一行 code 都有應該有意圖或是意義,所以都能命名。
註:
reliable : Kyle 說 named function expression 做 self-reference,其內部 function 是read only
,所以 reliable。
這部分我還在讀相關應用,比如 FP,不過不是很確定,就不敢多加著墨以免誤導。如果有其他想法,可以幫我補充有關read only
的相關運用。
如果只有 2-3 行 code, Kyle 會寫成 inline named function expression
如果有需要被 reference , Kyle 會寫成 (named) funtion declaration
Kyle 偏好 functional coding style, 有一本《Functional-Light JavaScript
》也是 open sourec。一樣是 named function
Kyle
不喜歡
Arrow Function,因為 Arrow Function 是 Anonymous 。
End。
(誒,不是,不要按叉叉關閉視窗。)
line 1 雖然很短,但你還是要看 funtion body 才能知道在做什麼。
line 1 可能是 self obvious,但你還是要讀 code。
line 3 雖然要打比較多字,但是看到 named 就可以知道 funtion 的意圖,而且非常顯式(obvious)
。
如果可以,與其用getId
,不如用getPersonId
orgetDefaultPersonId
,你可以提供更多訊息、意圖給看code的讀者,code 是先寫人看的,然後才是電腦。
Kyle 很不喜歡 promise chains 的可讀性
,很像古早時候寫 jQ
這時候可以用 function declaration 重構,避免過度巢狀,像是這種感覺:
function getDataFrom(person){
return getData(person.id)
}
getPerson().then( getDataFrom(person) );
後面文章會提到。
Kyle:『你這樣不是打更多字嗎???』
Kyle:『這樣不如還是用 function declaration。』
declaration
> function expression
named
>> anonymous
functions:
arrow funcions:
這邊的「reliable function self-reference」不知道是不是指說除了使用 named function expression 以外其他的方式都不可靠。
例如說如果 anonymous function 要做遞迴,其他的方式據我所知好像就只有 arguments.callee,但基本上已經是一個被禁掉/不推薦的用法。
所以如果一定要寫 function expression,要加名稱才能 self-reference
Kyle 有提到 arguments.callee 已經被廢棄(deprecated),所以他說在廢棄語法不使用的前提下除了named function expression之外沒有方法
。
這邊的 「reliable function self-reference」我不確定的是 read-only 這個敘述。
因為對比 reliable 的範例是,存一個變數在 enclosing ,那個 變數還是有可能被改動。
==> 所以 named function expression 的 {...} , 裡面的內容真的是 read-only ?