沒啥事情隨便寫了一個js的回調(diào)函數(shù)希望能幫助想要學(xué)習(xí)的(我接觸js時間不長,對回調(diào)的理解還是比較膚淺,如有錯誤希望大家指出 謝謝。){下一篇寫java 接口回調(diào)}
這里先引入幾個概念(baidu來的希望對大家有所幫助)
*函數(shù)也是對象
想弄明白回調(diào)函數(shù)罐监,首先的清楚地明白函數(shù)的規(guī)則。在javascript中,函數(shù)是比較奇怪的,但它確確實實是對象晨炕。確切地說,函數(shù)是用Function()構(gòu)造函數(shù)創(chuàng)建的Function對象毫炉。function對象包含一個字符串瓮栗,字符串包含函數(shù)的javascript代碼。假如你是從C語言或者java語言轉(zhuǎn)過來的瞄勾,這也許看起來很奇怪费奸,代碼怎么可能是字符串?但是對于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ù)作為回調(diào)
很容易把一個函數(shù)作為參數(shù)傳遞盗蟆。
function fn(arg1, arg2, callback){
var num = Math.ceil(Math.random() * (arg1 - arg2) + arg2);
callback(num); //傳遞結(jié)果
}
fn(10, 20, function(num){
console.log("Callback called! Num: " + num); //結(jié)果為10和20之間的隨機數(shù)
});
可能這樣做看起比較麻煩戈二,甚至有點愚蠢,為何不正常地返回結(jié)果喳资?但是當(dāng)遇上必須使用回調(diào)函數(shù)之時觉吭,你也許就不這樣認為了!
別擋道,傳統(tǒng)函數(shù)以參數(shù)形式輸入數(shù)據(jù)仆邓,并且使用返回語句返回值鲜滩。理論上,在函數(shù)結(jié)尾處有一個return返回語句节值,結(jié)構(gòu)上就是:一個輸入點和一個輸出點徙硅。這比較容易理解,函數(shù)本質(zhì)上就是輸入和輸出之間實現(xiàn)過程的映射搞疗。
但是嗓蘑,當(dāng)函數(shù)的實現(xiàn)過程非常漫長,你是選擇等待函數(shù)完成處理匿乃,還是使用回調(diào)函數(shù)進行異步處理呢桩皿?這種情況下,使用回調(diào)函數(shù)變得至關(guān)重要幢炸,例如:AJAX請求泄隔。若是使用回調(diào)函數(shù)進行處理,代碼就可以繼續(xù)進行其他任務(wù)宛徊,而無需空等佛嬉。實際開發(fā)中,經(jīng)常在javascript中使用異步調(diào)用闸天,甚至在這里強烈推薦使用巷燥!
*回調(diào)是什么?
看維基的 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百科:回調(diào)函數(shù)
回調(diào)函數(shù)就是一個通過函數(shù)指針調(diào)用的函數(shù)号枕。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù)缰揪,當(dāng)這個指針被用為調(diào)用它所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)葱淳《巯伲回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的赞厕,用于對該事件或條件進行響應(yīng)艳狐。
*******(認真看)因此,回調(diào)本質(zhì)上是一種設(shè)計模式皿桑,并且jQuery(包括其他框架)的設(shè)計原則遵循了這個模式毫目。
在JavaScript中蔬啡,回調(diào)函數(shù)具體的定義為:函數(shù)A作為參數(shù)(函數(shù)引用)傳遞到另一個函數(shù)B中,并且這個函數(shù)B執(zhí)行函數(shù)A镀虐。我們就說函數(shù)A叫做回調(diào)函數(shù)箱蟆。如果沒有名稱(函數(shù)表達式),就叫做匿名回調(diào)函數(shù)刮便。
因此callback 不一定用于異步空猜,一般同步(阻塞)的場景下也經(jīng)常用到回調(diào),比如要求執(zhí)行某些操作后執(zhí)行回調(diào)函數(shù)恨旱。
例子
一個同步(阻塞)中使用回調(diào)的例子辈毯,目的是在func1代碼執(zhí)行完成后執(zhí)行func2。
var func1=function(callback){
//do something.
(callback && typeof(callback) === "function") && callback();
}
var func2=function(){ }
func1(func2);
異步j(luò)query.ajax回調(diào)的例子
$.ajax({
type: "POST",
url: url,
data: {"key":JSON.stringify(), } ,
success:function(data){
//success回調(diào)
},
error:function(data){
//error回調(diào)
}
});
注意的是搜贤,ajax請求確實是異步的,不過這請求是由瀏覽器新開一個線程請求,當(dāng)請求的狀態(tài)變更時,如果先前已設(shè)置回調(diào),這異步線程就產(chǎn)生狀態(tài)變更事件放到 JavaScript引擎的處理隊列中等待處理谆沃。
下面貼上我今天寫的回調(diào)代碼~~~
<!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我是回調(diào)函數(shù)callbackF");
}
});
</script>
</html>
</html>
點擊test1 執(zhí)行 function test1(){...} 運行結(jié)果如下圖
點擊test2 執(zhí)行 function test2(){...} 運行結(jié)果如下圖
點擊test3 注意這里的test3執(zhí)行的function 去調(diào)用asyn并沒有傳入function參數(shù) 所以也就會在
if(typeof callBack=="function")
{
callBack(answer)
}else {
console.log("asyn:\tcallback不是function我沒法告訴他")
}
這里執(zhí)行else 不會執(zhí)行回調(diào)了 效果如下圖如有進一步討論的小伙伴請給我留言