CallBack Function & IIFE
參考資料:重新認識JS:Day18
Callback
同步、非同步
同步:Sync > 按部就班的做事 > 只有一個跑道,要過終點一個一個來
非同步:Async > 同時做事 > 多個跑道,三位跑者,可以一起跑
基本知識
一個函式被觸發了,才去被動地執行:我們可以說這是一個Callback Function
範例
在Async Await & Promise 出現之前,我們想要確保每個函式照順序去做,是用Callback Func。但若像以下傳入狀況,當系統一大,就會造成Callback Hell
// 為了確保先執行 funcA 再執行 funcB
// 我們在 funcA 加上 callback 參數
var funcA = function(callback){
var i = Math.random() + 1;
window.setTimeout(function(){
console.log('function A');
// 如果 callback 是個函式就呼叫它
if( typeof callback === 'function' ){
callback();
}
}, i * 1000);
};
var funcB = function(){
var i = Math.random() + 1;
window.setTimeout(function(){
console.log('function B');
}, i * 1000);
};
// 將 funcB 作為參數帶入 funcA()
funcA( funcB );
Callback Hell
getData(function (a) {
getMoreData(a, function (b) {
getMoreData(b, function (c) {
getMoreData(c, function (d) {
getMoreData(d, function (e) {
...
});
});
});
});
});
IIFE(立即被呼叫的函式)
問題
錯誤的 console.log跑法
// 假設想透過迴圈 + setTimeout 來做到
// 每秒鐘將 i 的值 console 出來
for( var i = 0; i < 5; i++ ) {
window.setTimeout(function() {
console.log(i);
}, 5000);
}
//5
//5
//5
//5
//5
因為 JS 切分變數的有效範圍最小單位為Function
而JS是非同步語言,所以執行上面的for,不會等setTimeout,而是執行階段就一次跑完,會讓 i = 5
流程: for 迴圈跑完 > setTimeout 執行(而那時的 i = 5 )(為啥會五次,因為setTimeout 跑了五次)
解決方法
利用 IIFE 在宣告的當下執行,之後不會再呼叫的特性
for( var i = 0; i < 5; i++ ) {
// 為了凸顯差異,我們將傳入後的參數改名為 x
// 當然由於 scope 的不同,要繼續在內部沿用 i 也是可以的。
(function(x){
window.setTimeout(function() {
console.log(x);
}, 1000);
})(i);
}
// 立刻執行把 i 放到 console.log(x) 中
// 一般函式改成 IIFE > 正常 func 先用小括號包起來,再執行自己
ES6的 let const
可以解決上述 定義域的問題
Last updated
Was this helpful?