为什么要在JavaScript中使用Call或Apply方法?除了参数的差别之外,普通方法调用和使用Call/Apply的主要区别是什么?如果您能通过场景举例加以解释,那就更好了。
在处理对象时,阅读以下两个指南可能会很有帮助,它们解释得非常清楚:
你可能已经知道,在JavaScript中函数是一等公民。这意味着你可以将它们作为参数传递给其他函数。
在某些情况下,你需要处理依赖于上下文的方法
。例如:
const button = document.querySelector('button');
const getRect = button.getBoundingClientRect;
getRect(); // TypeError...
// You have to pass a context fo that function
getRect.call(button);
还有一些其他传递上下文的函数。请查看apply
,bind
,call
等...
call
和apply
的另一个很好的使用示例是monkey-patching:
// Save the original console.log() method
var log = console.log;
console.log = function() {
// Invoke the original method with an additional parameter
log.apply(console, [(new Date()).toString()].concat(arguments));
};
Kyle Simpson在他的系列教程《你不知道的JavaScript》中有很好的解释。
class MyClass {
myProp = 'Hello World';
myMethod() {
console.log(this.myProp);
}
}
myMethod
。您需要执行以下操作:const myInstance = new MyClass();
document.querySelector('button').addEventListener('click', myInstance.myMethod);
addEventListener
时,执行上下文会发生变化,this
指向元素而不是类实例(该实例上没有myProp
属性)。如何将其改回来?在这种情况下,您可以使用bind
。document.querySelector('button').addEventListener('click', myInstance.myMethod.bind(myInstance));
function getFullName() {
return this.name + ' ' + this.lastname;
}
call
或apply
,该方法会默认当前实例(在这种情况下是window),并在当前对象上查找属性。但有时可能需要改变这种行为。比如说你有一个提供name
和lastname
属性的类,并且你想利用这个方法的功能。你可以这样做:class MyName {
name = 'Tom';
lastname = 'Hanks';
}
getFullName.apply(new MyName()); // --> 'Tom Hanks'
所以你看到了call
和apply
是如何有帮助的。您可以参考Zer0的答案,了解更多关于call
,apply
和bind
的信息。
这是关于在应用(apply)和调用(call)中的上下文(context)的问题。使用apply,您可以将参数传递给一个数组。
class MyObject {
constructor(operator) {
this.operator = operator;
}
calculate(a, b) {
switch(this.operator) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
}
}
}
const operators = [
new MyObject('+'),
new MyObject('-'),
new MyObject('*')
];
for (const op of operators) {
const func = op['calculate'];
console.log(func.call(op, 1, 1));
}