此示例中的函数doSomethingElse
无法执行,因为this
由于window
内部的无上下文调用而被反弹到global
或app.populateDatabase
(如果在Node中)。
有什么办法可以避免这种情况而不引用每个函数中的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))
一般来说,考虑转向承诺和可能是异步功能。然后这样做:
this.loadDatabase().then(() => this.doSomethingElse());
或者更好的异步功能:
await this.loadDatabase();
this.doSomethingElse();