JS:在无上下文函数调用中反弹 "this"
JS: Rebound "this" in contextless function call
此示例中的函数 doSomethingElse
执行失败,因为它的 this
由于无上下文调用而被重新绑定到 window
或 global
(如果在 Node 中) app.populateDatabase
.
里面
如果不在每个函数中引用 app
,有没有办法避免这种情况?
loadDatabase
函数根据逻辑语句执行回调,如果假想的数据库不存在,加载后填充它,然后 populateDatabase
执行它提供的回调。
我无法将 onLoaded
参数重新绑定到 app
,因为我不知道它来自哪里,而且 bind/apply/call 抽象过度使用会造成相当大的混乱。
var app = {};
app.loadDatabase = function(onLoaded) {
// If database already exists, only run a callback
var callback = onLoaded;
// If database doesn't exists, populate it, then run a callback.
if (!databaseExists) {
callback = this.populateDatabase.bind(this, onLoaded);
}
this.database = new sqlite.Database("file.db", function(error) {
if (error) { ... }
callback();
})
}
app.populateDatabase = function(onPopulated) {
// Contextless call here. <--------
onPopulated();
}
app.doSomethingElse = function() {
// this != app due to contextless call.
this.somethingElse();
}
app.run = function() {
// Load the database, then do something else.
this.loadDatabase(this.doSomethingElse);
}
app.run();
只需将 this.loadDatabase(this.doSomethingElse);
替换为 this.loadDatabase(() => this.doSomethingElse());
。这样你创建了一个新的箭头函数,然后 doSomethingElse
在正确的 this
上下文中被调用。
你也可以 .bind
但我推荐使用箭头函数。这里有 bind
:this.loadDatabase(this.doSomethingElse.bind(this))
通常考虑转向 promises 和异步函数。然后这样做:
this.loadDatabase().then(() => this.doSomethingElse());
或使用异步函数更好:
await this.loadDatabase();
this.doSomethingElse();
此示例中的函数 doSomethingElse
执行失败,因为它的 this
由于无上下文调用而被重新绑定到 window
或 global
(如果在 Node 中) app.populateDatabase
.
如果不在每个函数中引用 app
,有没有办法避免这种情况?
loadDatabase
函数根据逻辑语句执行回调,如果假想的数据库不存在,加载后填充它,然后 populateDatabase
执行它提供的回调。
我无法将 onLoaded
参数重新绑定到 app
,因为我不知道它来自哪里,而且 bind/apply/call 抽象过度使用会造成相当大的混乱。
var app = {};
app.loadDatabase = function(onLoaded) {
// If database already exists, only run a callback
var callback = onLoaded;
// If database doesn't exists, populate it, then run a callback.
if (!databaseExists) {
callback = this.populateDatabase.bind(this, onLoaded);
}
this.database = new sqlite.Database("file.db", function(error) {
if (error) { ... }
callback();
})
}
app.populateDatabase = function(onPopulated) {
// Contextless call here. <--------
onPopulated();
}
app.doSomethingElse = function() {
// this != app due to contextless call.
this.somethingElse();
}
app.run = function() {
// Load the database, then do something else.
this.loadDatabase(this.doSomethingElse);
}
app.run();
只需将 this.loadDatabase(this.doSomethingElse);
替换为 this.loadDatabase(() => this.doSomethingElse());
。这样你创建了一个新的箭头函数,然后 doSomethingElse
在正确的 this
上下文中被调用。
你也可以 .bind
但我推荐使用箭头函数。这里有 bind
:this.loadDatabase(this.doSomethingElse.bind(this))
通常考虑转向 promises 和异步函数。然后这样做:
this.loadDatabase().then(() => this.doSomethingElse());
或使用异步函数更好:
await this.loadDatabase();
this.doSomethingElse();