Javascript "this" overridden by an event listener

I'm probably doing something wrong, but I found interesting behavior when trying to apply some object oriented programs to Javascript. Consider the following

function Bug(element) { this.focusedCell = null; element.addEventListener('click', this.onClick, true); }; Bug.prototype.onClick = function(event){ console.log("this is: "); console.log(this); }; 

When I call a method from the console, I see the correct "this" instance, but when I click an element in the document, I see the document element instead of the instance. Therefore ... most likely, it is not a good idea to use event listeners using instance methods, at least in the way I do it.

So the question is:

  • Is it possible for such an event listener to call the instance method of a javascript object, keeping the instance in the call?

  • Is there a better way to do this?

Edit: I have not tried this in anything other than Chrome. But I would suggest that the behavior is the same.

+4
source share
3 answers

There is the best sample and does not require major changes. First I will show the code.

 function Bug(element) { this.focusedCell = null; // --------------------------------v----pass the object, not a function element.addEventListener('click', this, true); }; // Implement the `EventListener` interface Bug.prototype.handleEvent = function(event) { if (event.type === "click") this.onClick(event); } Bug.prototype.onClick = function(event) { console.log(JSON.stringify(this)); // '{"focusedCell":null}' console.log(event.currentTarget.nodeName); // "DIV" }; 

By adding the handleEvent method, we create the Bug EventListener interface. This allows us to pass a new Bug object as the second argument to addEventListener() instead of a function.

Now, when the "click" event occurs, the .handleEvent() method will be called, and the this value in this method will be the Bug object that was bound.


Since this is a reference to a Bug instance, this will obviously no longer be an element reference. But this is not necessary, since the element is available through event.currentTarget .

Of course, you can add an element directly to your Bug object in the constructor, if you want.

DEMO: http://jsfiddle.net/CnZTa/


+6
source

You can use Function.prototype.bind to create a listener related to what you want:

 function Bug(element) { this.focusedCell = null; element.addEventListener('click', this.onClick.bind(this), true); }; 

For older browsers (not ES5), a polyfill, such as MDN , is required.

+5
source

This is common JavaScript behavior. You can save the expected this by passing the function to the listener:

 function Bug(element) { var self = this; // Store a reference to this this.focusedCell = null; element.addEventListener('click', function() { // in here this refers to element self.onClick(event); }, true); }; Bug.prototype.onClick = function(event){ console.log("this is: "); console.log(this); // In here this refers the an instance of Bug. }; 
+1
source

Source: https://habr.com/ru/post/1480292/


All Articles