JS:在无上下文函数调用中反弹 "this"

JS: Rebound "this" in contextless function call

此示例中的函数 doSomethingElse 执行失败,因为它的 this 由于无上下文调用而被重新绑定到 windowglobal(如果在 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 但我推荐使用箭头函数。这里有 bindthis.loadDatabase(this.doSomethingElse.bind(this))


通常考虑转向 promises 和异步函数。然后这样做:

this.loadDatabase().then(() => this.doSomethingElse());

或使用异步函数更好:

await this.loadDatabase();
this.doSomethingElse();