JS: отскок "это" в вызове функции без контекста - PullRequest
0 голосов
/ 08 сентября 2018

Функция doSomethingElse в этом примере не выполняется, поскольку ее this был восстановлен до window или global (если он находится в узле) из-за вызова без контекста внутри 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();

1 Ответ

0 голосов
/ 08 сентября 2018

Просто замените 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();
...