iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
2
Modern Web

跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset系列 第 20

[day19] YDKJS (Scope) : Kyle Simpson 史上超級無敵討厭 匿名函式(Anonymous function)

  • 分享至 

  • xImage
  •  

大綱:

  1. Function Expression
  2. Naming Function Expression
  3. Arrow Function
  4. Function Types Hierarchy (summarize)

Function Expression

之前 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)

比較 function declarations 和 function expressions

  • function declarations
    • function scope 和 identifier 是一樣的 (line 1 是紅色小球, global scope)
  • function expressions
    • function expression 把他們的 identifier 放到自己的 scope
    • block statement 內會有 local lexical scope

    line 3 的 function anotherTeacher,是藍色小球 (local lexical scope)

這也就是為什麼 line 4 console 不會有 Error (因為是 local lexical scope )。
但是一樣的 code , line 9 因為 global 沒有宣告,所以會 ReferenceError

Why would you do this (function expression) ?

  1. 你通常看到是 匿名函式 (anonymous function)
  2. arrow function

Named Function Expression

不是幹話,就是有名字的 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個 理由。

  1. 可以做 self-reference (比如說 function recursion, event handler,needs to unbind self)
  2. more debuggable stack traces

    避免以下情形:

  3. More self-documenting code

    Kyle 一直強調,寫 code 是優先給人看,而且工程師透過 code 來溝通 (communicate more clearly your intent.)
    所以,避免誤解或混淆,最好的方法就是把 function 命名。

有時候 Kyle 想不到名字,會暫時性命名做 TODO ,因為他 commit 前會檢查所有 TODO,
這時候回來看 funtion 的目的就會比較容易命名。

如果你真的想不到名字:

  1. 你 funtion 寫太複雜,應該嘗試重構成小區塊
  2. 你不夠理解你的 code。

    每一行 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

Arrow Function

Kyle 不喜歡 Arrow Function,因為 Arrow Function 是 Anonymous 。

End。

(誒,不是,不要按叉叉關閉視窗。)


line 1 雖然很短,但你還是要看 funtion body 才能知道在做什麼。

line 1 可能是 self obvious,但你還是要讀 code。
line 3 雖然要打比較多字,但是看到 named 就可以知道 funtion 的意圖,而且非常顯式(obvious)
如果可以,與其用 getId ,不如用 getPersonId or getDefaultPersonId ,你可以提供更多訊息、意圖給看code的讀者,code 是先寫人看的,然後才是電腦。

  • 另一個例子:promise chains

Kyle 很不喜歡 promise chains 的可讀性,很像古早時候寫 jQ

這時候可以用 function declaration 重構,避免過度巢狀,像是這種感覺:

function getDataFrom(person){
    return getData(person.id)
}

getPerson().then( getDataFrom(person) );

Kyle 只有一種且唯一一種情境使用 arrow function : 需要 arrow 的 lexical behavor

後面文章會提到。

Kyle , arrow function 也可以命名啊!

Kyle:『你這樣不是打更多字嗎???』
Kyle:『這樣不如還是用 function declaration。』

Function Types Hierarchy (summarize)

  1. function declaration > function expression
  2. named >> anonymous

附註:一些 Kyle 的 code

functions:

arrow funcions:


上一篇
[day18] YDKJS (Scope) : Nested scope
下一篇
[day20] YDKJS (Scope) : Advanced Scope
系列文
跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
huli
iT邦新手 2 級 ‧ 2019-10-05 04:21:33

這邊的「reliable function self-reference」不知道是不是指說除了使用 named function expression 以外其他的方式都不可靠。

例如說如果 anonymous function 要做遞迴,其他的方式據我所知好像就只有 arguments.callee,但基本上已經是一個被禁掉/不推薦的用法。

所以如果一定要寫 function expression,要加名稱才能 self-reference

Ashe Li iT邦新手 5 級 ‧ 2019-10-05 04:39:37 檢舉

Kyle 有提到 arguments.callee 已經被廢棄(deprecated),所以他說在廢棄語法不使用的前提下除了named function expression之外沒有方法


這邊的 「reliable function self-reference」我不確定的是 read-only 這個敘述。

因為對比 reliable 的範例是,存一個變數在 enclosing ,那個 變數還是有可能被改動。

==> 所以 named function expression 的 {...} , 裡面的內容真的是 read-only ?

我要留言

立即登入留言