原文出處:匯智網
call()和apply()都是JavaScript 中函數對象上的方法:
var f = function () {};
'call' in f; // true
'apply' in f; // true
說到函數,JavaScript 中有個this的概念與函數調用相關,this指向一個對象,表示函數調用時的執行上下文;當在函數內引用this的時候,就會指向這個對象。
var man = {
name: 'Jason',
sayName: function() {
console.log(this.name);
}
}
man.sayName(); // 輸出'Jason'
上面的例子中,sayName()是對象man上的方法,sayName()里this指向sayName()所在的對象(即man),this.name實際上是man.name,因此最后輸出'Jason'。
如果函數不是對象上的方法,那this默認情況下會指向全局上下文,在瀏覽器中,也就是window:
window.name = 'Tommy'
function foo() {
console.log(this.name);
}
foo(); // `this`指向`window`,所以輸出'Tommy'
明白了this之后,call()和apply()就好解釋了。這兩個方法的作用是在函數調用時改變函數的執行上下文,也就是函數內的this;這兩個方法第一個參數,就是希望得到的this。
比如上面的foo函數,由於定義在全局環境中,this默認指向window;如果想更改里面指向的this,例如改成man,可以調用foo的call()方法,然后把man傳進來:
foo.call(man); // 輸出`man`
foo.apply(man); // 也是輸出`man`
兩個方法都可以更改函數執行時綁定的this;那它們有什么不同呢?主要是在傳參上。
假如foo定義時包括了形參:
window.name = 'Tommy'
function foo(a, b) {
console.log(a + b + this.name);
}
也就是說foo調用時期望傳進兩個參數,所以對於foo.call()和foo.apply()的形式,第一個參數指定綁定的this,后面的參數指定foo調用時期望傳入的參數(有2個);對於call來說,兩個參數一個一個傳進來;而對於apply來說,兩個參數必須組成一個數組,以數組方式傳進來:
foo.call(man, 'Hello, ', 'Mr.'); // 輸出‘Hello, Mr.Jason’
foo.apply(man, ['Hello, ', 'Mr.']); // 同樣輸出‘Hello, Mr.Jason’
比較下直接調用foo的結果
foo('Hello, ', 'Mr.'); 輸出‘Hello, Mr.Tommy’
