告訴你什么是JavaScript回調函數(shù)

沒啥事情隨便寫了一個js的回調函數(shù)希望能幫助想要學習的(我接觸js時間不長,對回調的理解還是比較膚淺,如有錯誤希望大家指出 謝謝。){下一篇寫java 接口回調}

這里先引入幾個概念(baidu來的希望對大家有所幫助)

*函數(shù)也是對象

想弄明白回調函數(shù),首先的清楚地明白函數(shù)的規(guī)則。在javascript中,函數(shù)是比較奇怪的,但它確確實實是對象。確切地說,函數(shù)是用Function()構造函數(shù)創(chuàng)建的Function對象。function對象包含一個字符串,字符串包含函數(shù)的javascript代碼。假如你是從C語言或者java語言轉過來的,這也許看起來很奇怪,代碼怎么可能是字符串?但是對于javascript來說,這很平常。數(shù)據(jù)和代碼之間的區(qū)別是很模糊的。

//可以這樣創(chuàng)建函數(shù)
var fn = new Function("arg1", "arg2", "return arg1 * arg2;");
fn(3, 7); // return 3*7=21

這樣做的一個好處,可以傳遞代碼給其他函數(shù),也可以傳遞正則變量或者對象(因為代碼字面上只是對象而已)。

*傳遞函數(shù)作為回調

很容易把一個函數(shù)作為參數(shù)傳遞。

function fn(arg1, arg2, callback){
 var num = Math.ceil(Math.random() * (arg1 - arg2) + arg2);
 callback(num);  //傳遞結果
}
 fn(10, 20, function(num){
 console.log("Callback called! Num: " + num);  //結果為10和20之間的隨機數(shù) 
});   

可能這樣做看起比較麻煩,甚至有點愚蠢,為何不正常地返回結果?但是當遇上必須使用回調函數(shù)之時,你也許就不這樣認為了!
  別擋道,傳統(tǒng)函數(shù)以參數(shù)形式輸入數(shù)據(jù),并且使用返回語句返回值。理論上,在函數(shù)結尾處有一個return返回語句,結構上就是:一個輸入點和一個輸出點。這比較容易理解,函數(shù)本質上就是輸入和輸出之間實現(xiàn)過程的映射。
  但是,當函數(shù)的實現(xiàn)過程非常漫長,你是選擇等待函數(shù)完成處理,還是使用回調函數(shù)進行異步處理呢?這種情況下,使用回調函數(shù)變得至關重要,例如:AJAX請求。若是使用回調函數(shù)進行處理,代碼就可以繼續(xù)進行其他任務,而無需空等。實際開發(fā)中,經常在javascript中使用異步調用,甚至在這里強烈推薦使用!

*回調是什么?

看維基的 Callback_(computer_programming) 條目:

In computer programming, a callback is a reference to a piece of executable code that is passed as an argument to other code.

jQuery文檔How jQuery Works#Callback_and_Functio...條目:

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed. The special thing about a callback is that functions that appear after the "parent" can execute before the callback executes. Another important thing to know is how to properly pass the callback. This is where I have often forgotten the proper syntax.

baidu百科:回調函數(shù)

回調函數(shù)就是一個通過函數(shù)指針調用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當這個指針被用為調用它所指向的函數(shù)時,我們就說這是回調函數(shù)?;卣{函數(shù)不是由該函數(shù)的實現(xiàn)方直接調用,而是在特定的事件或條件發(fā)生時由另外的一方調用的,用于對該事件或條件進行響應。
*******(認真看)因此,回調本質上是一種設計模式,并且jQuery(包括其他框架)的設計原則遵循了這個模式。
在JavaScript中,回調函數(shù)具體的定義為:函數(shù)A作為參數(shù)(函數(shù)引用)傳遞到另一個函數(shù)B中,并且這個函數(shù)B執(zhí)行函數(shù)A。我們就說函數(shù)A叫做回調函數(shù)。如果沒有名稱(函數(shù)表達式),就叫做匿名回調函數(shù)。
因此callback 不一定用于異步,一般同步(阻塞)的場景下也經常用到回調,比如要求執(zhí)行某些操作后執(zhí)行回調函數(shù)。
例子
一個同步(阻塞)中使用回調的例子,目的是在func1代碼執(zhí)行完成后執(zhí)行func2。

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

異步jquery.ajax回調的例子

   $.ajax({
                    type: "POST",
                    url: url,
                    data: {"key":JSON.stringify(),  } ,
                    success:function(data){
                       //success回調
                   },
                    error:function(data){
                   //error回調
                    }
                });

注意的是,ajax請求確實是異步的,不過這請求是由瀏覽器新開一個線程請求,當請求的狀態(tài)變更時,如果先前已設置回調,這異步線程就產生狀態(tài)變更事件放到 JavaScript引擎的處理隊列中等待處理。

下面貼上我今天寫的回調代碼~~~

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BlackWingJsCallBackFunctionTest</title>
</head>
<script type="text/javascript" src="../js/jquery-3.2.1.min.js"></script>
<body>
<button onClick=test1()>test1()</button>
<button onClick=test2()>test2()</button>
<button onClick=test2()>test3()</button>
</body>
<script language="JavaScript" type="text/javascript">
    var callbackF;
    var questionTest1="1+1";
    var questionTest2="what are you doing?";
    function asyn(question,callBack,type)
    {
      console.log("asyn:\t你好我是asyn,我知道了你的問題是"+question+",算好我告訴你")


      if(type==1)
      {

          console.log("asyn:\t你妹的1+1=2")
           answer=2;
      }else if(type==2)
      {
          console.log("asyn:\t我在等人請我?guī)兔?我可以做很多事情(很多情況下耗時操作)")
           answer="我在等人請我?guī)兔?我可以做很多事情(很多情況下耗時操作)"
      }
      if(typeof callBack=="function")
      {
          callBack(answer)
      }else {
          console.log("asyn:\tcallback不是function我沒法告訴他")
      }
    }
    function b(answer){
        console.log("b:\t我收到了你的答案是"+answer);
        callbackF();
    }
    function c(answer){
        console.log("c:\t我收到了你的答案是"+answer);
        callbackF();
    }
    function test1() {
        console.log("test1:\t你好asyn,幫我算個問題,算好了告訴b")
        asyn(questionTest1,b,1);
    }
    function test2() {
        console.log("test2:\t你好asyn,what are you doing?,請回答c")
        asyn(questionTest2,c,2);
    }
    function test3() {
        console.log("test3:\t你好asyn,我傳入去參數(shù)不是function");
        asyn("1+1","...",3)
    }
    $(function(){
        callbackF = function(){
            console.log("callbackF:\t我是回調函數(shù)callbackF");
        }
    });
</script>
</html>
</html>

點擊test1 執(zhí)行 function test1(){...} 運行結果如下圖


image.png

點擊test2 執(zhí)行 function test2(){...} 運行結果如下圖


image.png

點擊test3 注意這里的test3執(zhí)行的function 去調用asyn并沒有傳入function參數(shù) 所以也就會在
 if(typeof callBack=="function")
      {
          callBack(answer)
      }else {
          console.log("asyn:\tcallback不是function我沒法告訴他")
      }

這里執(zhí)行else 不會執(zhí)行回調了 效果如下圖
image.png

如有進一步討論的小伙伴請給我留言

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容