JavaScript中的括號問題

JavaScript中的括號問題

之前在上一堂線上課程時,發現js在執行函式時有無括號的不同,有一位同學給出的解答我覺得很有幫助,翻譯出來給大家參考。

這篇文章譯自課程The Modern JavaScript Bootcamp中的一篇問答。這堂課雖然號稱開給初心者,但後半都是實作項目,雖然很有趣,但會碰到一些較進階的問題,且老師不一定有時間解答,而且有時候老師回答的超級簡短,若是沒辦法搞清楚,可能會懵懵懂懂不知道自己在幹嘛。

前情提要

這份實作是要做出一個使用者在填寫搜尋欄位時,欄位會綁定監聽器,將輸入值與API的資料匹配.自動跳出符合結果的Autocomplete小工具,其中為了讓Ajax請求送出的頻率不要太過頻繁,原課程中使用了一個名為debounce的函式,這個函式中包含一個負責根據欄位輸入來送出請求的閉包。接著在input欄位綁定監聽,執行debounce。但是為什麼事件發生時執行的不是debounce而是裡面的閉包?造成很多人的疑問。

以下原文搭配中文譯文,因為提及該課堂作業的一些程式碼,為了讓讀者好理解,做過一些刪減

正文

When you initially load up your JS code, the code gets evaluated by the JS Engine.
在程式碼執行之前,會被js的引擎評估

To a JS parser, the two lines are different: each producing unique outcome
對js的編譯器來說,以下這兩行是不同的,產生的結果也完全不同

inputValue.addEventListener("input", debounce(onInput, 500));

inputValue.addEventListener("input", debounce);

The first line tells the ENGINE to invoke the debounce function immediately and replace it with its result.
第一行告訴引擎直接執行這個函式,並且將它替換成它的結果

the anonymous closure is the result it produces, which ,as Stephen states above, gets repeatedly executed, each time a user types something into the input field
結果就是它內部所含的匿名閉包,正如stephen(講者)所說,這個閉包會在使用者輸入欄位時被重複執行

The second line just references a function name that shall be executed when the input event is triggered.
第二行則是說當input事件發生時在執行這個函式

Here’s a little demo :
這裡是一點小示範

Imagine you have two, typical function declarations that you wish to assign to a particular object : ROBOT in our example :
想像你有兩個宣告方式一樣的函式,你想將這兩個函式分派給一個物件:robot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

//宣告

function identity(){
return this
}

//宣告
function whoAmI(){
return ` Who am I ?
${name}

`}



//物件

let robot= {

name: " I am a Robot",

identity:identity, //沒有括號

whoAmI:whoAmI() //有括號

}



console.log(robot.identity());
console.log(robot.whoAmI());

執行結果

Pay close attention how the two functions are being assigned/ referenced inside of the robot object.
請注意看看這兩個在robot物件中是怎麼被指派的。

when the robot has its methods invoked , one of those methods - robot.whoAmI() - produces an error.
當robot使用這兩個函式時,其中一個-robot.whoAmI()出錯了

As you can see from the image above, robot.whoAmI no longer points to the function .
如你所見,此時robot.whoAmI不再指向一個函式

And that is correct with accordance to this line :
但是根據這行程式碼, 這其實是正確的結果

whoAmI:whoAmI()

The line tells the ENGINE to invoke the whoAmI function immediately and replace it with its result.
這一行程式碼告訴引擎馬上執行這個函式, 並且用它產生的結果替換它

而whoami產生的結果就是回傳一個字串,而字串並不是一個函式,所以也無法被呼叫。

結論:

inputValue.addEventListener("input", debounce(onInput, 500));
而在原文的程式碼中,debounce函式在addEventListener被掛上時,其實就執行過了,它會被替換成裡面的閉包函式,這個函式才是監聽器被觸發時真正被呼叫的,也會接收到event。

也就是說,js的編譯器在遇到括號時就會馬上執行,這也是立即執行函式(IIFE)的基礎。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×