When using bind()
on an Event Listener in JavaScript I can no longer get the element with "this".
Here is my code:
function callback(){
console.log(this.someVar);
// Works fine
console.log(this);
// No longer refers to the element, outputs "Object"
}
callback = callback.bind({someVar: 1234});
element.addEventListener('click', callback);
Any idea on how to fix this?
When using bind()
on an Event Listener in JavaScript I can no longer get the element with "this".
Here is my code:
function callback(){
console.log(this.someVar);
// Works fine
console.log(this);
// No longer refers to the element, outputs "Object"
}
callback = callback.bind({someVar: 1234});
element.addEventListener('click', callback);
Any idea on how to fix this?
Share Improve this question edited Nov 2, 2019 at 21:37 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Nov 2, 2019 at 20:56 OodOod 1,8054 gold badges27 silver badges50 bronze badges 12-
3
That is what
bind
does - it sets thethis
context permanently. If you don't want this behaviour, then perhaps you shouldn't usebind
. – VLAZ Commented Nov 2, 2019 at 21:00 - What output are you getting? – Kalesh Kaladharan Commented Nov 2, 2019 at 21:00
- @VLAZ what can I use as an alternative? – Ood Commented Nov 2, 2019 at 21:02
- @KaleshKaladharan "Object" – Ood Commented Nov 2, 2019 at 21:03
- 2 @VLAZ I want to pass a variable to the function in the event but this variable is constantly changing. When the event fires I want the function to output the value of the variable from the time the EventListener was created. – Ood Commented Nov 2, 2019 at 21:10
4 Answers
Reset to default 2If you want to pass one variable but keep the this
context, then you can use currying or partial application:
Curry
Your function has to receive a value and return another function. This way you can do the following:
function callback(num) {
return function() {
console.log(num);
console.log(this.id);
}
}
var number = 1;
document.getElementById("hello").addEventListener("click", callback(number));
//change the variable
number = 2;
document.getElementById("world").addEventListener("click", callback(number));
//change the variable again
number = 3;
<button id="hello">Hello</button>
<button id="world">World</button>
Partial application
Same idea but instead of having your callback return a new function, it will just take a single argument and work normally, you need another function that will do the partial application:
function callback(num) {
console.log(num);
console.log(this.id);
}
var number = 1;
document.getElementById("hello").addEventListener("click", partial(callback, number));
//change the variable
number = 2;
document.getElementById("world").addEventListener("click", partial(callback, number));
//change the variable again
number = 3;
function partial(fn, arg) {
return function() {
return fn.call(this, arg);
}
}
<button id="hello">Hello</button>
<button id="world">World</button>
The partial application function can be generalised to handle any amount or arguments
In ES6:
function partial(fn, ...args) {
return function(...otherArgs) {
return fn.apply(this, [...args, ...otherArgs]);
}
}
In ES5:
function partial(fn) {
var args = [].prototype.slice.call(arguments, 1);
return function() {
var otherArgs = [].[].prototype.slice.call(arguments);
return fn.apply(this, args.concat(otherArgs));
}
}
The bind()
method creates a new function that, when called, has its this
keyword set to the provided value.
So, when you call a function like
callback = callback.bind({someVar:1234})
this
inside the function callback will be the object {someVar:1234}
To access someVar
in the callback function, you have to use this.someVar
.
I hope this helps.
If you are still unclear refer this article https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
You can still use event.target and can get access to the clicked element.
function callback(event){
console.log(this.someVar);
// Works fine
console.log(event.target);
// No longer refers to the element, outputs "Object"
}
callback = callback.bind({someVar: 1234});
element.addEventListener('click', callback);
You can call bind() only once. After bind() called, this
reference is bind to the argument. So the even can not be assigned to this
. For example:
function f() {return this;}
f = f.bind({a:1});
f(); // => {a:1}
f = f.bind({a:2}); // this is what addEventListener actually do as if it bind this to even
f(); // {a:1}
addEventListener cannot bind this again.