天天看點

javascript 中函數調用方法:apply() 和 call()

每個函數都包含兩根非繼承而來的方法:apply()和call()。

這兩個方法的用途都是在特定的作用域中調用函數,實際上等于設定函數體内this對象的值。

首先,apply()方法接收兩個參數:一個是在其中運作函數的作用域,另一個是參數數組。其中第二個參數可以是Array的執行個體,也可以是arguments對象。例如:

function sum(num1,num2) {
    return num1+num2;
}

function callSum1(num1,num2) {
    return sum.apply(this,arguments);//傳入arguments對象
}

function callSum2(num1,num2) {
    return sum.apply(this,[num1,num2]);//傳入數組
}

alert(callSum1(,));   //20
alert(callSum2(,));   //20           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在上面的例子中,callSum1在執行sum()函數時傳入了this作為this值(因為是在全局作用域中調用的,是以傳入的就是window對象)和arguments對象。而callSum2同樣也調用了sum()函數,但它傳入的則是this 和一個參數數組。這兩個函數都會正常執行并傳回正确的結果。

注:在嚴格模式下,未指定環境對象而調用函數,則this不會轉型為window。除非明确把函數添加到某個對象或者調用apply()或call(),否則this 的值将是undefined。

call()方法和apply()方法的作用相同,它們的差別僅在于接收參數的方式不同。對于call()方法而言,第一個參數this值沒有變化,變化的是其與參數都直接傳遞給函數。換句話說,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來,如下面的例子所示。

function sum(num1,num2) {
    return num1+num2;
}
function callSum(num1,num2) {
    return sum.call(this,num1,num2);//逐個傳入每一個參數
}

alert(callSum(,));   //20           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

事實上,傳遞參數并非aplly()和call()真正的用武之地;它們真正強大的地方在于是能夠擴充函數賴以運作的作用域。下面來看一個人例子。

window.color = "red";
var o = { color:"blue" };
function sayColor() {
    alert(this.color);
}

sayColor();   //red
sayColor.call(window);   //red
sayColor.call(o);    //blue           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

這個例子是在前面說明this對象的示例基礎上修改而成的。這一次,sayColor()也是作為全局函數定義的,而且當在全局作用域中調用它時,它确實會顯示”red”—-因為對this.color的求值會轉換成對window.color的求值。但是,當運作sayColor.call(o)時,函數的執行環境就不一樣了,是以此時函數體内的this對象指向了o,于是結果就顯示的是”blue”。

使用call()和apply()來擴充作用域的最大好處,就是對象不需要與方法有任何耦合的關系。

繼續閱讀