Как уже упоминалось, причина, по которой вы получаете undefined
, заключается в this
в функциях вашего обработчика событий , а не экземпляре класса (как вы ожидаете).
У вас есть три способа исправить это , два из которых основаны на ES5, один из них основан на ES6 (что не должно быть проблемой - вы уже используете ES6 в своем коде).
1 Явно привяжите внешний this
к функциям вашего обработчика, используя Function.prototype.bind()
.
bind()
, который сообщает функциям, что использовать в качестве this
внутри тела функции.
class Test {
constructor() {
this.movable = true;
this.move = false;
this.div = document.createElement("div");
this.div.classList.add("block");
this.div.addEventListener("mousemove", function() {
console.log(this.movable);
}.bind(this)); // .bind(this)
this.div.addEventListener("mousedown", function() {
this.move = true;
console.log("test");
}.bind(this)); // .bind(this)
this.div.addEventListener("mouseup", function() {
this.move = false;
console.log("test1");
}.bind(this)); // .bind(this)
}
add() {
this.div.textContent = "Test";
document.body.appendChild(this.div);
}
remove() {
document.body.removeChild(this.div);
}
}
var test = new Test();
test.add();
<body>
</body>
2 Сохраните ссылку на экземпляр класса в переменной (здесь: self
) и используйте ее внутри функции-обработчика.
Раньше это был очень распространенный шаблон для решения проблемы, с которой вы столкнулись.Сейчас, когда все прыгают на поезд ES6, он все меньше и меньше используется.Мне нравится это также для улучшения читаемости.
class Test {
constructor() {
const self = this; // reference to this stored in self
this.movable = true;
this.move = false;
this.div = document.createElement("div");
this.div.classList.add("block");
this.div.addEventListener("mousemove", function() {
console.log(self.movable); // self instead of this used
});
this.div.addEventListener("mousedown", function() {
self.move = true; // self instead of this used
console.log("test");
});
this.div.addEventListener("mouseup", fucntion() {
self.move = false; // self instead of this used
console.log("test1");
});
}
add() {
this.div.textContent = "Test";
document.body.appendChild(this.div);
}
remove() {
document.body.removeChild(this.div);
}
}
var test = new Test();
test.add();
<body>
</body>
3 Использовать синтаксис функции стрелки ES6.
Функции стрелок не имеют своих собственных this
(что может быть недостатком в некоторыхслучаи!), что делает "внешний" this
доступным для них.
class Test {
constructor() {
this.movable = true;
this.move = false;
this.div = document.createElement("div");
this.div.classList.add("block");
this.div.addEventListener("mousemove", () => {
console.log(this.movable);
});
this.div.addEventListener("mousedown", () => {
this.move = true;
console.log("test");
});
this.div.addEventListener("mouseup", () => {
this.move = false;
console.log("test1");
});
}
add() {
this.div.textContent = "Test";
document.body.appendChild(this.div);
}
remove() {
document.body.removeChild(this.div);
}
}
var test = new Test();
test.add();
<body>
</body>
Как уже упоминалось, если не использовать функции стрелок для определения обработчиков событий, this
внутри обработчика будет обычно содержать ссылку на элемент, вызвавший событиена (что часто очень полезно).Чтобы получить к ней доступ, несмотря на использование функций стрелок, вы можете использовать свойство event.target
:
// notice I name a parameter e here
// which will hold the event object
// that is always passed to the event
// handler automatically - it just needs
// a name to make it accessible inside
(e) => { console.log(e.target); }