javascript - 将回调作为值传递和作为扩展箭头函数传递之间的区别
问题描述
传递回调时,按值执行:
utility.subscribe(this.callback);
与将其作为扩展形式传递不同吗?
utility.subscribe(arg => this.callback(arg));
我理解它们是等效的,但是当需要将上下文与回调一起传递时遇到了问题。
var utility = {
name: 'utility',
subscribe(callback) {
var msgForCallback = 'Hey callback!';
callback(msgForCallback);
}
}
var user = {
name: 'user',
useSubscriber() {
utility.subscribe(
this.callback
);
},
useSubscriberWithArrow() {
utility.subscribe(
arg => this.callback(arg)
);
},
callback (arg) {
console.log(`Context: ${this.name}`);
console.log(`The utility says: ${arg}`);
}
}
console.log('\nCall user.useSubscriber();');
user.useSubscriber();
console.log('\nCall user.useSubscriberWithArrow();');
user.useSubscriberWithArrow();
我意识到回调函数是一个常规函数,这就是上下文可能丢失的原因。所以我尝试将其更改为箭头函数,但即使是带有扩展回调的调用也会丢失上下文。
callback: (arg) => { .. }
代替
callback (arg) { .. }
var utility = {
name: 'utility',
subscribe(callback) {
var msgForCallback = 'Hey callback!';
callback(msgForCallback);
}
}
var user = {
name: 'user',
useSubscriber() {
utility.subscribe(
this.callback
);
},
useSubscriberWithArrow() {
utility.subscribe(
arg => this.callback(arg)
);
},
callback: (arg) => {
console.log(`Context: ${this.name}`);
console.log(`The utility says: ${arg}`);
}
}
console.log('\nCall user.useSubscriber();');
user.useSubscriber();
console.log('\nCall user.useSubscriberWithArrow();');
user.useSubscriberWithArrow();
解决方案
要了解您的代码有什么问题,您首先必须了解
regular function
声明和arrow function
声明之间的区别。arrow function's this
绑定到它的环境this
(即它被定义的地方)。其次,您必须了解, a 中的函数
object method
不指向'this' of the object
,而是指向global this
ie,如下所示:
let obj = {
someMethod() {
function someFun() {
// here 'this' points to 'global this'
// i.e. 'this' does not points to obj
}
}
}
我想以上几点很清楚......
现在,来到你的代码:
首先重写callback
为regular function
. 不要把它写成arrow
.
我在下面的代码中提供了更多的行(用于调试目的):
let utility = {
name: 'utility',
subscribe(callback) {
let msgForCallback = 'Hey callback!';
callback(msgForCallback);
}
};
let user = {
name: 'user',
useSubscriber() {
utility.subscribe(this.callback);
},
useSubscriberWithArrow() {
utility.subscribe(arg => this.callback(arg + " With Arrow Huh "));
},
callback(arg) {
console.log('this: ');
console.log(this);
console.log("-----------");
console.log(`Context: ${this.name}`);
console.log(`The utility says: ${arg}`);
console.log("__________________________________________________________________________");
}
};
console.log('\nCall user.useSubscriber();');
user.useSubscriber();
console.log('\nCall user.useSubscriberWithArrow();');
user.useSubscriberWithArrow();
我们将讨论上面给出的代码有什么问题。
this.name
代码的错误是 user.useSubscriber() 在被调用时将无法解析callback
。
为什么?
注意:user.callback()
不是arrow
函数,而是常规函数并传递给utility.subscribe()
. 所以,它变成了,就像我上面描述的第二点一样,function with in object method
,所以,this
将绑定到global this
。您可以通过运行代码来证明这一点。代码的输出有点像下面(我已经测试过node v10.16.*
):
Call user.useSubscriber();
this:
Object [global] {
DTRACE_NET_SERVER_CONNECTION: [Function],
DTRACE_NET_STREAM_END: [Function],
DTRACE_HTTP_SERVER_REQUEST: [Function],
DTRACE_HTTP_SERVER_RESPONSE: [Function],
...
...
-----------
Context: undefined
The utility says: Hey callback!
__________________________________________________________________________
Call user.useSubscriberWithArrow();
this:
{ name: 'user',
useSubscriber: [Function: useSubscriber],
useSubscriberWithArrow: [Function: useSubscriberWithArrow],
callback: [Function: callback] }
-----------
Context: user
The utility says: Hey callback! With Arrow Huh
__________________________________________________________________________
我想,这解决了问题。
现在,为什么user.useSubscriberWithArrow()
有效:
它有效,请记住我在第一点中讨论过的内容 - arrow function is bind to it's environments 'this'(i.e. where it is defined)
。所以,你传递了一个arrow
函数 as callback
,而不是user.callback()
它本身,它arrow function
用于调用this.callback()
. 并且,arrow's
this
绑定到user
,因为它是在user
对象中定义的。
我想这可以解决你的问题。如果您还有问题,请在评论中问我...
推荐阅读
- java - Hystrix 回退方法最佳实践
- php - PHP 致命错误:调用未定义函数 pg_pconnect()
- r - R循环太长
- excel - 需要 Excel VBA 将 B、C、D 列复制到 A 列
- reactjs - 简单反应全栈中的 sitemap.xml
- angular - ngx-smart-modal 中的 Select2 插件不起作用
- vba - Document_Open 在 Word 2007 模板中不起作用
- django - 如何在 Django 上制作 robots.txt
- android - GSON 解析 JSON 字符串
- python - Django 中的整个应用程序因单个错误而关闭