teelou teelou - 14 days ago 9
Javascript Question

ES6 - How to access `this` element after binding `this` class?

How can I access

this
element after binding
this
class?

For example, without binding
this
:

$(".button-open").click(function(event) {
console.log(this); // <a href="#" class="button-open">Open</a>
this.openMe();
});


With binding
this
:

$(".button-open").click(function(event) {
console.log(this); // Polygon {windowHeight: 965, scrollNum: 0}
this.openMe();
}.bind(this));


How can I get and access
<a href="#" class="button-open">Open</a>
again after binding
this
?

Full code:

class Polygon {
constructor() {
this.windowHeight = $(window).height();
this.scrollNum = 0;
}

// Simple class instance methods using short-hand method
// declaration
init() {
var clickMe = this.clickMe.bind(this);
return clickMe();
}

clickMe() {
$(".button-open").click(function(event) {
console.log(this);
this.openMe();
}.bind(this));


$(".button-close").click(function(event) {
this.closeMe();
}.bind(this));
}

openMe() {
console.log(this.scrollNum); // 0
this.scrollNum = 200;
console.log(this.scrollNum); // 200
return false;

}

closeMe() {
console.log(this.scrollNum); // 200
return false;
}
}

export { Polygon as default}


Any ideas?

EDIT:

The same issue with jQuery
animate
:

$(".element").animate({}, 'fast', 'swing', function(event) {
console.log(this); // the element
}.bind(this));


After binding:

$(".element").animate({}, 'fast', 'swing', function(event) {
console.log(this); // undefined
}.bind(this));


Any global or bulletproof way of getting the
element
again?

Answer

1. The best option would be to store the context in a variable and don't overwrite this:

var context = this;
$('.element').on('click', function(event) {
  // context would be the this you need
  // this is the element you need
});

2. If you're only targeting a single element, you can do the reverse from above and save the element on which you're binding the handler into a variable and then use the variable inside the handler:

var el = $('.element');
el.on('click', function(event) {
  // use el here
}.bind(this));

Since you tagged the question with ES6, it might be better to bind the context with an arrow function because using bind is more verbose and also creates an additional function:

var el = $('.element');
el.on('click', (event) => {
  // this is the same as in the outer scope
  // use el here
});

3. Another option is to use the target property of the event object but this can also be any child within your element (the target is the element that dispatches the event, not the element on which you bounded the handler), thus it might require traversing up the DOM tree to find the element you need, which is less efficient.

var el = $('.element');
el.on('click', ({ target }) => {
  while (target.parentNode && !target.classList.contains('element')) {
    target = target.parentNode;
  }
  // here the target should be the element you need
});