call, apply都屬於Function.prototype的方法
它們是在 JavaScript 引擎內在實現的,因爲屬於Function.prototype,所以每個Function對象實例,也就是每個方法都有call, apply屬性。它們的作用一樣,只是使用方式不同。
call 與 apply 調用參數不同
不同之處在於調用apply函數時,參數可以使用數組; call要求明確列出參數。
助記法: Apply 的A表示 Array, 即數組, 而 Call 的 C 表示 Comma, 即逗號。
更多請參閱MDN的文檔。
僞語法:
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
從ES6開始,還有展開spread數組與該call功能一起使用的可能性,你可以在這裏看到兼容性。
示例代碼:
function theFunction(name, profession) {
console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // 使用展開語法
搞這麼複雜,直接調用函數不好嗎?
主要是爲了模擬面向對象,對狀態進行封裝的同時, 不同實例可以有不同的內部狀態,如:
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); // 函數在全局範圍內調用,this=window
// 會輸出: undefined, 因爲window下沒有定義x
unboundGetX.call(module) //輸出 42, 或使用 bind 也有同樣的效果
var module1 ={
x:123,
getX: unboundGetX //this 變爲module1
}
module1.getX() //返回123