Доброго времени суток!
JS осваиваю недавно, раньше программировал на C#. Не могу разобраться, что я делаю не так. Убил несколько часов, прочитал про: контекст, замыкания, стрелочные функции, bind, call и прочее... но так и не понял.
Есть класс EventEmitter, "наследуясь" от которого можно получить возможность генерировать кастомные "события". Есть класс Model, генерирующая "change" при изменении данных и есть некий компонент (класс Component), который получает ссылку на модель.
Я хочу, подписать создаваемый компонент на событие модели - прямо в конструторе. Но как не извращаюсь, не могу получить нужно значение this в обработчике события. Всё время this ссылается только на компонент, созданный последним (((
Приводимый ниже код - базовый вариант (вокруг него уже поставлено множество экспериментов):
spoiler// Базовый класс, позволяющий подписывать на события.
class EventEmitter {
constructor() {
this.handlers = {};
}
on(eventName, handler) {
if (eventName in this.handlers) {
this.handlers[eventName].push(handler);
} else {
this.handlers[eventName] = [ handler ];
}
};
emit(eventName, args) {
if (eventName in this.handlers) {
for (var handler of this.handlers[eventName]) {
setTimeout(() => { handler(); }, 0);
}
}
}
}
// Модель данных триггерит событие change, при изменении.
class Model extends EventEmitter {
constructor() {
super();
}
set(entries) {
const keys = Object.keys(entries);
keys.forEach(key => {
this[key] = entries[key];
});
this.emit('change', keys);
}
}
// Класс компонента. При создании подписывается на изменение модели.
class Component extends EventEmitter {
constructor(settings, model) {
super();
this.isActive = false;
this.model = model;
this.uses = settings.uses;
if (settings.children) {
this.children = {};
for (let child of Object.entries(settings.children)) {
var key = child[0], componentSettings = child[1];
// Все дочерние компоненты создаются рекурсивно и получают ссылку на ту же модель, что и родитель.
this.children[key] = new Component(componentSettings, this.model);
}
}
model.on('change', () => {
// Здесь будет более сложная логика, но пока нужно разобраться с this.
console.log(settings);
console.log(this);
});
}
}
var model = new Model();
var view = new Component({
template: 'gameLayout',
children: {
player: {
template: 'player',
slot: '#player',
uses: [ 'player' ]
},
menu: {
template: 'menu',
slot: '#menu'
},
question: {
template: 'question',
slot: '#question',
uses: [ 'question' ]
}
}
}, model);
model.set({ property: 'value' });
В общем, в очередной раз понимаю, что ничего не понимаю в JS..
Если кто-то сможет объяснить, в чём я ошибаюсь, или хотя просто показать, как правильно, буду очень благодарен.
С уважением, Сергей.
P. S. Особенно раздражает момент, что когда я просматриваю в консоли model.handlers - там показано, что каждый handler в замыкании имеет свой объект settings... но выводится всё равно одно и то же. В общем, упёрся (