【发布时间】:2020-11-29 21:46:53
【问题描述】:
为什么我们在 java 脚本中使用 Call 或 Apply 方法?除了发送参数来调用方法的差异之外,普通方法调用和使用 Call/Apply 之间的主要区别是什么?如果你能用一个场景解释一下吗?
【问题讨论】:
标签: javascript arrays function apply call
为什么我们在 java 脚本中使用 Call 或 Apply 方法?除了发送参数来调用方法的差异之外,普通方法调用和使用 Call/Apply 之间的主要区别是什么?如果你能用一个场景解释一下吗?
【问题讨论】:
标签: javascript arrays function apply call
在处理对象时会很有帮助,我建议你阅读这两个指南,它们解释得很好:
【讨论】:
您可能知道,函数是 JavaScript 中的一等公民。这意味着您可以将它们作为参数传递给其他函数。
在某些情况下,您正在处理依赖于上下文的 methods。例如:
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 在他的系列中有很好的解释You don't know JS
【讨论】:
我可以举两个例子来解释为什么它很重要。假设您有一个如下所示的类:
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));
这实质上将引用更改回类。这只是一个例子。可能有很多示例,您希望更改方法的当前执行上下文。我们再举一个例子:
假设有一个第三方函数需要访问某些类成员。
第三方函数需要目标实例的name 和lastname 属性。
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 的信息。
【讨论】:
这是关于应用与调用中的 this 上下文。应用你可以在数组中传递参数。
【讨论】:
你还可以通过它从不同的对象中访问同名的函数,例如 toString() 或任何你喜欢的:
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));
}
【讨论】: