JS函數呼叫(4種方法)

2020-07-16 10:05:06
JavaScript 提供了 4 種函數呼叫:一般形式的函數呼叫、作為物件的方法呼叫、使用 call 和 apply 動態呼叫、使用 new 間接呼叫。

一般形式的函數呼叫

在預設狀態下,函數是不會被執行的。使用小括號()可以啟用並執行函數。在小括號中可以包含零個或多個引數,引數之間通過逗號進行分隔。

範例1

在下面範例中,使用小括號呼叫函數,然後直接把返回值傳入函數,進行第二次運算,這樣可以節省兩個臨時變數。
function f(x,y) {  //定義函數
    return x * y;  //返回值
}
console.log(f(f(5,6), f(7,8)));  //返回1680。重複呼叫函數

範例2

如果函數返回值為一個函數,則在函數呼叫時可以使用多個小括號反復呼叫。
function f(x,y) {  //定義函數
    return function () {  //返回函數型別的資料
        return x * y;
    }
}
console.log(f(7,8) ());  //返回56,反復呼叫函數

範例3

設計遞回呼叫函數,即在函數內呼叫自身,這樣可以反復呼叫,但最終返回的都是函數自身。
function f() {  //定義函數
    return f;  //返回函數自身
}
console.log(f() () () () () () () () () () () ());  //返回函數自身
當然,上述設計方法在實際開發中沒有任何應用價值,不建議使用。

作為物件的方法呼叫

當一個函數被設定為物件的屬性值時,稱之為方法。使用點語法可以呼叫一個方法。

範例

下面範例建立一個 obj 物件,它有一個 value 屬性和一個 increment 屬性。increment 方法接收一個可選引數,如果該引數不是數位,那麼預設使用數位 1。
var obj = {
    value : 0,
    increment : function (inc) {   
        this.value += typeof inc === 'number' ? inc :1;
    }
}
obj.increment();
console.log(obj.value);  //1
obj.increment(2);
console.log(obj.value);  //2
使用點語法可以呼叫物件 obj 的方法 increment,然後通過 increment 方法改寫 value 屬性的值。在 increment 方法中可以使用 this 存取 obj 物件,然後使用 obj.value 方式讀寫 value 屬性值。

使用 call 和 apply 動態呼叫

call 和 apply 是 Function 的原型方法,它們能夠將特定函數當做一個方法系結到指定物件上,並進行呼叫。具體用法如下:

function.call(thisobj, args...)
function.apply(thisobj, [args])

function 表示要呼叫的函數;引數 thisobj 表示系結物件,即 this 指代的物件;引數 args 表示要傳遞給被呼叫函數的引數。call 方法可以接收多個參數列,而 apply 只能接收一個陣列或者偽類陣列,陣列元素將作為參數列傳遞給被呼叫的函數。

範例1

下面範例使用 call 動態呼叫函數 f,並傳入引數值 3 和 4,返回運算值。
function f(x,y) {  //定義求和函數
    return x + y;
}
console.log(f.call (null, 3, 4));  //返回7
在上面範例中,f 是一個簡單的求和函數,通過 call 方法把函數 f 係結到空物件 null 身上,以實現動態呼叫函數 f,同時把引數 3 和 4 傳遞給函數 f,返回值為 7。實際上,f.call(null,3,4) 等價於 null.m(3,4)。

範例2

上面範例使用 call 呼叫,實際上也可以使用 apply 方法來呼叫函數 f。
function f(x,y) {  //定義求和函數
    return x + y;
}
console.log(f.apply(null, [3,4]));  //返回7
如果把一個陣列或偽類陣列的所有元素作為引數進行傳遞,使用 apply 方法就非常便利。

範例3

下面使用 apply 方法設計一個求最大值得函數。
function max() {  //求最大值函數
    var m = Number.NEGATIVE_INFINITY;  //宣告一個負無窮大的數值
    for (var i = 0; i < arguments.length; i ++) {  //遍歷所有實參
        if (arguments[i] > m)  //如果實參值大於變數m
        m = arguments[i];  //則把該實參值賦值給m
    }
    return m;  //返回最大值
}
var a = [23,45,2,46,62,45,56,63];  //宣告並初始化陣列
var m = max.apply(Object, a);  //動態呼叫max,係結為Object的方法
console.log(m);  //返回63
在上面範例中,設計定義一個函數 max(),用來計算所有引數中的最大值引數。首先通過 apply 方法動態呼叫 max() 函數,然後把它繫結為 Object 物件的一個方法,並把包含多個值的陣列傳遞給它,最後返回經過 max() 計算後的最大陣列元素。

如果使用 call 方法,就需要把陣列所有元素全部讀取出來,再逐一傳遞給 call 方法,顯然這種做法不是很方便。

範例4

也可以動態呼叫 Math 的 max() 方法來計算陣列的最大值元素。
var a = [23,45,2,46,62,45,56,63];  //定義並初始化陣列
var m = Math.max.apply(Object, a);  //呼叫系統函數max
console.log(m);  //返回63

範例5

使用 call 和 apply 方法可以把一個函數轉換為指定物件的方法,並在這個物件上呼叫該方法。當函數動態呼叫之後,這個物件的臨時方法也就不存在了。
function f() {
    return "函數f";
}
var obj = {};
f.call(obj);  //把函數f系結為obj物件的方法
console.log(obj.f());  //再次呼叫該方法,則返回編譯錯誤

call 和 apply 方法的主要功能如下:
  • 呼叫函數。
  • 修改函數體內的 this 指代物件。
  • 為物件系結方法。
  • 跨越限制呼叫不同型別的方法。

本小節主要介紹了如何使用 call 和 apply 方法呼叫函數,由於涉及型別、物件和 this 知識,後續我們還會繼續深入講解。

new 命令間接呼叫

使用 new 命令可以範例化物件,這是它的主要功能,但是在建立物件的過程中會啟用並執行函數。因此,使用 new 命令可以間接呼叫函數。

範例

下面範例簡單演示了如何用 new 命令,把傳入的引數值顯示在控制台。
function (x,y) {  //定義函數
    console.log("x =" + x + ", y =" + y);
}
new f(3,4);
使用 new 命令呼叫函數時,返回的是物件,而不是 return 的返回值。如果不需要返回值,或者 return 的返回值是物件,則可以選用 new 間接呼叫函數。