簡析JavaScript中的Function型別(三)——作為值的函式
因為在ECMAScript中,函式名本身就是變數,所以函式也可以作為值來使用。也就是說,不僅可以像傳遞引數一樣把一個函式傳遞給另一個函式,而且可以將一個函式作為另一個函式的結果返回。
1. 作為引數
來看一個示例:
function callFn(fn, param){ return fn(param); } function add5(num){ return num + 5; } var value = callFn(add5, 10); console.log(value);//15
首先聲明瞭一個callFn
函式,它接收兩個引數,一個是要呼叫的函式,另一個是傳遞給要呼叫函式的引數。接下來建立了add5
函式,然後使用callFn
呼叫了add5
,返回了add5
的結果。
其實這裡使用匿名函式作為引數也是可以的,還是這個例子:
var value = callFn(function(num){
return num + 5;
}, 10);
console.log(value);//15
看到這是不是覺得有點熟悉呢?其實類似的,我們一直在用:
setTimeout(function(){
console.log('hello world');
}, 1000);
上面這段程式碼我想讀者一定不陌生吧,這是一個延遲函式,1秒鐘後執行第一個引數——匿名函式。setTimeout
window
上的全域性函式,第一個引數是要執行的回撥函式,第二個引數是延遲的毫秒數。
再來看另一個例子:
$('#id').click(function(){
console.log('點選了');
});
這是jQuery中的寫法,$()
是一個函式呼叫,這個函式接收的引數是'#id'
,返回了一個jQuery物件,在這個物件上再呼叫click()
方法,這個方法接收一個匿名函式作為引數,這樣就完成了click事件的繫結。
下面是jQuery 3.3.1版本131~144行的程式碼,我們看到jQuery
就是一個函式。
var version = "3.3.1", // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }, // Support: Android <=4.0 only // Make sure we trim BOM and NBSP rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
這是第10333~10358行:
var
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$;
jQuery.noConflict = function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}
if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}
return jQuery;
};
// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( !noGlobal ) {
window.jQuery = window.$ = jQuery;
}
對於其中的邏輯我們大可不必理會,從中可以看出,這段程式碼大致做了這樣一件事:
window.jQuery = window.$ = jQuery;
這樣就能理解,為什麼我們可以使用$()
了,$()
和jQuery()
是等同的。
2. 作為返回值
先來看一段程式碼:
var arr = [8, 1, 35, 3, 10];
//升序
function ascSort(v1, v2) {
return v1 - v2;
}
arr.sort(ascSort);
console.log(arr);//[1, 3, 8, 10, 35]
//降序
function descSort(v1, v2){
return v2 - v1;
}
arr.sort(descSort);
console.log(arr);//[35, 10, 8, 3, 1]
這是JavaScript陣列(一)——排序中講的給陣列排序的程式碼,我們看到升序和降序分別聲明瞭一個函式,現在我們想能不能把這兩個函式合併為一個呢?來看下面的程式碼:
var arr = [8, 1, 35, 3, 10];
function comparisonFn(flag){
if(flag){
// true 升序
return function(v1, v2){
return v1 - v2;
}
}else{
// false 降序
return function(v1, v2){
return v2 - v1;
}
}
}
arr.sort(comparisonFn(false));
console.log(arr);//[35, 10, 8, 3, 1]
如程式碼所示,我們建立了一個函式,把真正的比較函式作為這個函式的返回值,在使用的時候通過給comparisonFn()
傳遞true/false
來控制升降序,達到了簡化程式碼的目的。
關於函式作為引數和返回值的例子還有很多,這裡就不一一列舉了,相信讀者隨著對JavaScript學習的不斷深入,以後還