JS—回撥函式

狸xun尋發表於2018-03-31

在JavaScript中,回撥函式具體的定義為:函式A作為引數(函式引用)傳遞到另一個函式B中,並且這個函式B執行函式A。我們就說函式A叫做回撥函式。如果沒有名稱(函式表示式),就叫做匿名回撥函式。

因此callback 不一定用於非同步,一般同步(阻塞)的場景下也經常用到回撥,比如要求執行某些操作後執行回撥函式。

例子

一個同步(阻塞)中使用回撥的例子,目的是在func1程式碼執行完成後執行func2。

var func1=function(callback){
    //do something.
    (callback && typeof(callback) === "function") && callback();
}

func1(func2);
    var func2=function(){
}複製程式碼

非同步回撥的例子:

$(document).ready(callback);

$.ajax({
  url: "test.html",
  context: document.body
}).done(function() { 
  $(this).addClass("done");
}).fail(function() { alert("error");
}).always(function() { alert("complete"); 
});
/**
注意的是,ajax請求確實是非同步的,不過這請求是由瀏覽器新開一個執行緒請求,當請求的狀態變更時,如果先前已設定回撥,這非同步執行緒就產生狀態變更事件放到 JavaScript引擎的處理佇列中等待處理。見:http://www.phpv.net/html/1700.html
*/複製程式碼
回撥什麼時候執行

回撥函式,一般在同步情境下是最後執行的,而在非同步情境下有可能不執行,因為事件沒有被觸發或者條件不滿足。

回撥函式的使用場合
  • 資源載入:動態載入js檔案後執行回撥,載入iframe後執行回撥,ajax操作回撥,圖片載入完成執行回撥,AJAX等等。
  • DOM事件及Node.js事件基於回撥機制(Node.js回撥可能會出現多層回撥巢狀的問題)。
  • setTimeout的延遲時間為0,這個hack經常被用到,settimeout呼叫的函式其實就是一個callback的體現
  • 鏈式呼叫:鏈式呼叫的時候,在賦值器(setter)方法中(或者本身沒有返回值的方法中)很容易實現鏈式呼叫,而取值器(getter)相對來說不好實現鏈式呼叫,因為你需要取值器返回你需要的資料而不是this指標,如果要實現鏈式方法,可以用回撥函式來實現
  • setTimeout、setInterval的函式呼叫得到其返回值。由於兩個函式都是非同步的,即:他們的呼叫時序和程式的主流程是相對獨立的,所以沒有辦法在主體裡面等待它們的返回值,它們被開啟的時候程式也不會停下來等待,否則也就失去了setTimeout及setInterval的意義了,所以用return已經沒有意義,只能使用callback。callback的意義在於將timer執行的結果通知給代理函式進行及時處理。
回撥函式的傳遞

上面說了,要將函式引用或者函式表示式作為引數傳遞。

$.get('myhtmlpage.html', myCallBack);//這是對的
$.get('myhtmlpage.html', myCallBack('foo', 'bar'));//這是錯的,那麼要帶引數呢?
$.get('myhtmlpage.html', function(){//帶引數的使用函式表示式
myCallBack('foo', 'bar');
});複製程式碼

另外,最好保證回撥存在且必須是函式引用或者函式表示式:
(callback && typeof(callback) === "function") && callback();

相關文章