標籤:
既然函數可以像其他資料那樣賦值給某個個變數,可以被定義、刪除、拷貝,那為什麼就不能被當成參數傳遞給其他函數呢?
下面的樣本中,我們定義了一個以兩個函數為參數的函數。該函數會分別執行這兩個參數函數,並返回它們的傳回值之和。
function invoke_and_add(a,b){ return a() + b(); }
現在讓我們來簡單定義一下這兩個參與加法運算的函數,它們只是單純地返回一個寫入程式碼值:
function one(){ return 1;}function two(){ return 2; }
下面,我們只需將這兩個函數傳遞給目標函數 invoke_and_add(),就可以得到執行結果了:
invoke_and_add(one ,two);
3
事實上,我們也可以直接用匿名函數來代替one()和two(),以作為目標函數的參數,例如:
invoke_and_add(function(){return 1;},function(){return 2;})
當我們將函數A傳遞給函數B,並由B來執行A時,A就成了一個回呼函數(callback functions)。如果這時A還是一個無名函數,我們就稱它為匿名回呼函數。
那麼,應該什麼時候使用回呼函數呢?下面就讓我們通過幾個應用執行個體來示範一下回呼函數的優勢。
* 它可以讓我們在不做命名的情況下傳遞函數(這意味著可以節省全域變數)。
* 我們可以將一個函數叫用作業委託給另一個函數(這意味著可以節省一些代碼編寫工作)。
* 它們也有助於提升效能。
回調樣本:
在編程過程中,我們通常需要將一個函數的傳回值傳遞給另一個函數。在下面的例子中,我們定義了兩個函數:第一個multiplayByTwo(),該函數會通過一個迴圈將其所接受的三個參數分別乘以2,並以數組的形式返回結果;第二個函數addOne()只接受一個值,然後將它加1並返回即可。
function multiplyByTwo(a,b,c){ var i,ar =[]; for (i=0;i<3;i++){ ar[i] = arguments[i]*2;} return ar; }function addOne(a){ return a+1;}
現在,我們來測試一下這兩個函數:
multiplyByTwo(1,2,3);
[2,4,6]
addOne(100)
101
接下來,我們要實現這三個元素在兩個函數之間的傳遞,這需要定義一個用於儲存元素的數組。我們先從multiplyByTwo()的調用開始:
var myarr =[];
myarr=multiplyByTwo(10,20,30);
[20,40,60]
然後,用迴圈遍曆每個元素,並將它們分別傳遞給addOne()。
for(var i=0;i<3;i++){myarr[i] =addOne(myarr[i]);}
myarr
[21,41,61]
如你所見,這段代碼可以工作,但是顯然還有一定的改善空間。特別是這裡使用了兩個迴圈,如果資料量很大或迴圈操作很複雜的話,開銷一定不小。因此,我們需要將它們合二為一。這就需要對multiplyByTwo()函數做一些改動,使其接受一個回呼函數,並在每次迭代操作中調用它。具體如下:
function multiplyByTwo(a,b,c,callback){ var i,ar=[]; for(i=0;i<3;i++){ ar[i]=callback(arguments[i]*2); } return ar;}
函數修改完成之後,之前的工作只需要一次函數調用就夠了,我們只需像下面這樣將初始值和回呼函數傳遞給它即可:
myarr= multiplyByTwo(1,2,3,addOne);
[3,5,7]
我們還可以用匿名函數來代替addOne(),這樣做可以節省一個額外的全域變數。
myarr= multiplyByTwo(1,2,3,function(a){return a +1});
[3,5,7]
而且,使用匿名函數也更易於隨時根據需求調整代碼。例如:
myarr = multiplyByTwo(1,2,3,function(a){return a +2});
[4,6,8]
javascript 的回呼函數