JavaScript是一個單執行緒、同步的程式,它逐行執行程式碼,並不會非同步的執行程式。
剛最近翻過很多文章,有的文章寫是同步有的寫非同步搞得我好亂啊!
不過我整理了一下應該可以解釋成這樣會比較好:
Javascript 是一種「單執行續 (Single-Thread)」的語言,可以執行非同步事件。
單執行續
意思就是一次只能做一件事情,如果安排了很多事情要給他做,他就會讓這些事情去排隊,再一件一件做,逐行執行。這就是所謂的同步,一次只做一件事情。
那為什麼JS可以執行非同步事件呢?
因為當我們在執行 Javscript 的時候,Javascript 是在瀏覽器內執行的。
瀏覽器還提供了很多 WebAPI (ex: document、XMLHttpRequest、setTimeout) 給我們使用,他們不在 V8 引擎中,也是我們無法取得的內容,我們只能呼叫這些功能去執行他,當瀏覽器知道你要呼叫他們來用的時候,就可以和你的程式碼同時一起執行 (Concurrency) ,也不會影響到你的 JS 主程式,
所以在瀏覽器內,只有 Javascript 引擎本身是同步的,而 Javascript 引擎可以跟 WebAPI 溝通,達到非同步的事件處理。
同步
的概念有點像是要先完成一件事情才會做下一件事。
舉例來說,假設今天你是一位廚師要做一個料理,一定會先選菜→洗菜→切菜→炒菜→出菜都是一人作業,
每個動作執行完上一個動作在去做下一個動作。
非同步
的概念就是而是在收到食材的同時,負責洗菜的廚師就去處理洗菜,負責炒菜的廚師就去處理炒菜。
這樣就可以達到處理事件的流程不會被「卡住」,就是非同步 (Asynchronous) 的概念。
同步
光看字面上就可能把它想成是「所有動作同時進行」,但事實上比較像是「一步一步來處理」的意思。 而非同步
則是我不用等待 A 做完才做 B、C,而是這三個事情可以同時發送出去。
立即執行函式也稱 Immediately Invoked Function Expression
,簡稱 IIFE,是一個在宣告的當下就會馬上被執行的函式。
IIFE寫法如下:
(function IIFE() {
console.log("立即函式");
})();
另外,立即函式無法在函式外被再次執行:
(function IIFE() {
console.log("立即函式");
})();
console.log(IIFE); //跳錯
用一個括號將函式包起來,後面馬上直接在接一個()
。那寫這個立即執行函式有什麼好處?
function sayHello() {
console.log("Hello!");
}
function sayHello() {
console.log("Hey!");
}
sayHello() //會跳出Hey!
這樣第二個函式會蓋過第一個函式的結果!那如果我們是這樣寫:
function sayHello() {
console.log("Hello!");
}
(function sayHello() {
console.log("Hey!");
})() //Hey!
// sayHello() //Hello!
就是可以減少「全域變數」的產生,同時也避免了變數名稱衝突的機會。現在IIFE有自己的作用域,因此不會污染到其他區域,Hello
也就不會被覆蓋。當然如果想要傳入參數也是可以的!
(function (a, b) {
console.log(a + b);
})(3, 4);
重新認識 JavaScript: Day 18 Callback Function 與 IIFE
重新認識 JavaScript: Day 26 同步與非同步