У меня есть единственный элемент на моей странице, и мне нужно обнаруживать события mosuedown и mouseup. Он работает нормально, но я решил переместить весь свой javascript внутри класса. вот что я придумал до сих пор:
class MyRectangle {
constructor(elementId) {
this.frame = $("#" + elementId);
this.setListener();
}
setListener() {
this.frame.on("mousedown", function(evt) {
evt.preventDefault();
console.info("MOUSE DOWN" + " " + evt.pageX + ", " + evt.pageY);
$(document).bind("mouseup", this.docMouseUp);
});
}
docMouseUp(evt) {
console.info("MOUSE UP" + " " + evt.pageX + ", " + evt.pageY);
$(document).unbind("mouseup", this.docMouseUp);
}
}
var myRect = new MyRectangle("rectangle");#rectangle {
width: 100px;
height: 100px;
background-color: #dfca45;
}<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id = "rectangle">
</div>Таким образом, событие mouseup никогда не запускается.
JSFiddle: https://jsfiddle.net/5hd7672v/



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема в том, что внутри docMouseUp и обратного вызова для функций событий mousedownthis больше не ссылается на экземпляр MyRectangle. Это потому, что эти функции вызываются jQuery, а контекст (переменная this) устанавливается на элемент, который сгенерировал событие.
Чтобы исправить это, вы можете привязать экземпляр MyRectangle следующим образом:
let self = this;
this.frame.on("mousedown", function(evt) {
evt.preventDefault();
console.info("MOUSE DOWN" + " " + evt.pageX + ", " + evt.pageY);
$(document).bind("mouseup", self.docMouseUp.bind(self));
});
РЕДАКТИРОВАТЬ
Я пропустил звонок $(document).bind("mouseup", self.docMouseUp);.
Чтобы это работало, вам нужно изменить ссылку на docMouseUp, чтобы она указывала на ту же функцию, которая была установлена как обратный вызов.
class MyRectangle {
constructor(elementId) {
this.frame = $("#" + elementId);
this.setListener();
}
setListener() {
let self = this;
this.docMouseUp = this.docMouseUp.bind(this);
this.frame.on("mousedown", function(evt) {
evt.preventDefault();
console.info("MOUSE DOWN" + " " + evt.pageX + ", " + evt.pageY);
$(document).bind("mouseup", self.docMouseUp);
});
}
docMouseUp(evt) {
console.info("MOUSE UP" + " " + evt.pageX + ", " + evt.pageY);
$(document).unbind("mouseup", this.docMouseUp);
}
}
var myRect = new MyRectangle("rectangle");#rectangle {
width: 100px;
height: 100px;
background-color: #dfca45;
}<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = "rectangle">
</div>@CertainPerformance Это зависит от того, в этом случае неиспользование стрелочной функции дает возможность jQuery устанавливать контекст внутри анонимной функции.
@CertainPerformance не может использовать их в IE на один раз: caniuse.com/#feat=arrow-functions
@Titus отвязка не работает должным образом. Обратные вызовы складываются, если вы нажимаете чаще.
Лучше использовать стрелочные функции, чем сохранять текущую ссылку
thisв отдельной переменной - это антишаблон.