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