Как получить правильный `this` внутри колбэка?
У меня есть функция конструктора, которая регистрирует обработчик события:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Мок-объект transport
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// вызывается как
var obj = new MyConstructor('foo', transport);
Однако я не могу получить доступ к свойству data
созданного объекта внутри колбэка. Похоже, что this
не ссылается на созданный объект, а на какой-то другой.
Я также пытался использовать метод объекта вместо анонимной функции:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
Но это приводит к тем же проблемам.
Как мне получить доступ к правильному объекту?
4 ответ(ов)
Всё дело в "магическом" синтаксисе вызова метода:
object.property();
Когда вы вызываете метод непосредственно из объекта, контекст выполнения будет указывать на сам объект. Если же вы выполните тот же метод, но разделите процесс на два шага, контекст будет глобальным (например, window
):
var f = object.property;
f();
Когда вы получаете ссылку на метод, он больше не привязан к объекту. Это обычная ссылка на функцию. То же самое происходит, когда вы используете эту ссылку в качестве колбэка:
this.saveNextLevelData(this.setAll);
В таком случае, вам нужно привязать контекст к функции:
this.saveNextLevelData(this.setAll.bind(this));
Если вы используете jQuery, лучше применять метод $.proxy
, поскольку bind
не поддерживается во всех браузерах:
this.saveNextLevelData($.proxy(this.setAll, this));
Мы не можем привязать контекст this
к функции setTimeout()
, так как она всегда выполняется в контексте глобального объекта (Window). Если вы хотите получить доступ к контексту this
внутри функции обратного вызова, вы можете использовать метод bind()
, чтобы привязать нужный контекст. В результате это будет выглядеть так:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
Таким образом, благодаря bind(this)
вы сможете вызвать метод methodName()
с правильным контекстом.
Я столкнулся с проблемой в функции xAxisTickFormatting
для линейного графика Ngx
, которая вызывалась из HTML следующим образом: [xAxisTickFormatting]="xFormat"
.
Я не мог получить доступ к переменной компонента из объявленной функции. Однако, данное решение помогло мне исправить ситуацию и правильно получить контекст this
.
Вместо использования функции вот так:
xFormat(value): string {
return value.toString() + this.oneComponentVariable; // даёт неверный результат
}
Используйте следующий вариант:
xFormat = (value) => {
// console.log(this);
// теперь у вас есть доступ к переменным компонента
return value + this.oneComponentVariable;
}
Таким образом, вы сможете получить доступ к вашим переменным компонента и избежать проблем с контекстом.
Вы можете использовать стрелочную функцию, чтобы избежать проблемы с контекстом this
. Вот как это можно сделать:
const functionToTest = (dataToSet, transport) => {
this.dataToSet = dataToSet;
transport.on('dataToSet', () => {
console.log(this.dataToSet);
});
}
В данной реализации стрелочная функция сохраняет значение this
из окружающего контекста, что позволяет вам правильно ссылаться на this.dataToSet
внутри обработчика события. Это решает проблему, с которой вы можете столкнуться при использовании обычной функции для обработчика.
Как работает ключевое слово "this" и когда его следует использовать?
Как передать параметр в колбек setTimeout()?
В чем разница между String.slice и String.substring?
Существует ли ссылка на "последнюю" библиотеку jQuery в Google APIs?
Как создать диалог с кнопками "Ок" и "Отмена"