How to access the correct `this` inside a callback?
up vote
1013
down vote
favorite
I have a constructor function which registers an event handler:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
However, I'm not able to access the data
property of the created object inside the callback. It looks like this
does not refer to the object that was created but to an other one.
I also tried to use an object method instead of an anonymous function:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
but it exhibits the same problems.
How can I access the correct object?
javascript callback this
add a comment |
up vote
1013
down vote
favorite
I have a constructor function which registers an event handler:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
However, I'm not able to access the data
property of the created object inside the callback. It looks like this
does not refer to the object that was created but to an other one.
I also tried to use an object method instead of an anonymous function:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
but it exhibits the same problems.
How can I access the correct object?
javascript callback this
57
From time to time I’m so fed up with a certain kind of question, that I decide to write a canonical answer. Even though these questions have been answered like a million times, it’s not always possible to find a good question + answer pair which is not “polluted” by irrelevant information. This is one of those moments and one of those questions (and I’m bored). If you think that there is actually a good existing canonical question/answer for this type of question, let me know and I will delete this one. Suggestions for improvements are welcome!
– Felix Kling
Nov 29 '13 at 6:13
Related: Preserving a reference to “this” in JavaScript prototype functions
– Bergi
Mar 1 '14 at 12:46
Related: “this” keyword in event methods when using JavaScript prototype object
– Bergi
Sep 9 '14 at 20:43
1
Useful TypeScript page about this, mostly applicable to JS too.
– Ondra Žižka
Feb 1 '17 at 21:49
add a comment |
up vote
1013
down vote
favorite
up vote
1013
down vote
favorite
I have a constructor function which registers an event handler:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
However, I'm not able to access the data
property of the created object inside the callback. It looks like this
does not refer to the object that was created but to an other one.
I also tried to use an object method instead of an anonymous function:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
but it exhibits the same problems.
How can I access the correct object?
javascript callback this
I have a constructor function which registers an event handler:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
However, I'm not able to access the data
property of the created object inside the callback. It looks like this
does not refer to the object that was created but to an other one.
I also tried to use an object method instead of an anonymous function:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
but it exhibits the same problems.
How can I access the correct object?
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
javascript callback this
javascript callback this
edited Jul 11 '17 at 18:32
T.J. Crowder
670k11611841281
670k11611841281
asked Nov 29 '13 at 6:13
Felix Kling
539k123842892
539k123842892
57
From time to time I’m so fed up with a certain kind of question, that I decide to write a canonical answer. Even though these questions have been answered like a million times, it’s not always possible to find a good question + answer pair which is not “polluted” by irrelevant information. This is one of those moments and one of those questions (and I’m bored). If you think that there is actually a good existing canonical question/answer for this type of question, let me know and I will delete this one. Suggestions for improvements are welcome!
– Felix Kling
Nov 29 '13 at 6:13
Related: Preserving a reference to “this” in JavaScript prototype functions
– Bergi
Mar 1 '14 at 12:46
Related: “this” keyword in event methods when using JavaScript prototype object
– Bergi
Sep 9 '14 at 20:43
1
Useful TypeScript page about this, mostly applicable to JS too.
– Ondra Žižka
Feb 1 '17 at 21:49
add a comment |
57
From time to time I’m so fed up with a certain kind of question, that I decide to write a canonical answer. Even though these questions have been answered like a million times, it’s not always possible to find a good question + answer pair which is not “polluted” by irrelevant information. This is one of those moments and one of those questions (and I’m bored). If you think that there is actually a good existing canonical question/answer for this type of question, let me know and I will delete this one. Suggestions for improvements are welcome!
– Felix Kling
Nov 29 '13 at 6:13
Related: Preserving a reference to “this” in JavaScript prototype functions
– Bergi
Mar 1 '14 at 12:46
Related: “this” keyword in event methods when using JavaScript prototype object
– Bergi
Sep 9 '14 at 20:43
1
Useful TypeScript page about this, mostly applicable to JS too.
– Ondra Žižka
Feb 1 '17 at 21:49
57
57
From time to time I’m so fed up with a certain kind of question, that I decide to write a canonical answer. Even though these questions have been answered like a million times, it’s not always possible to find a good question + answer pair which is not “polluted” by irrelevant information. This is one of those moments and one of those questions (and I’m bored). If you think that there is actually a good existing canonical question/answer for this type of question, let me know and I will delete this one. Suggestions for improvements are welcome!
– Felix Kling
Nov 29 '13 at 6:13
From time to time I’m so fed up with a certain kind of question, that I decide to write a canonical answer. Even though these questions have been answered like a million times, it’s not always possible to find a good question + answer pair which is not “polluted” by irrelevant information. This is one of those moments and one of those questions (and I’m bored). If you think that there is actually a good existing canonical question/answer for this type of question, let me know and I will delete this one. Suggestions for improvements are welcome!
– Felix Kling
Nov 29 '13 at 6:13
Related: Preserving a reference to “this” in JavaScript prototype functions
– Bergi
Mar 1 '14 at 12:46
Related: Preserving a reference to “this” in JavaScript prototype functions
– Bergi
Mar 1 '14 at 12:46
Related: “this” keyword in event methods when using JavaScript prototype object
– Bergi
Sep 9 '14 at 20:43
Related: “this” keyword in event methods when using JavaScript prototype object
– Bergi
Sep 9 '14 at 20:43
1
1
Useful TypeScript page about this, mostly applicable to JS too.
– Ondra Žižka
Feb 1 '17 at 21:49
Useful TypeScript page about this, mostly applicable to JS too.
– Ondra Žižka
Feb 1 '17 at 21:49
add a comment |
8 Answers
8
active
oldest
votes
up vote
1352
down vote
accepted
What you should know about this
this
(aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scopes like other variables (except for arrow functions, see below). Here are some examples:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
To learn more about this
, have a look at the MDN documentation.
How to refer to the correct this
Don't use this
You actually don't want to access this
in particular, but the object it refers to. That's why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self
and that
.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Since self
is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that you can access the this
value of the callback itself.
Explicitly set this
of the callback - part 1
It might look like you have no control over the value of this
because its value is set automatically, but that is actually not the case.
Every function has the method .bind
[docs], which returns a new function with this
bound to a value. The function has exactly the same behaviour as the one you called .bind
on, only that this
was set by you. No matter how or when that function is called, this
will always refer to the passed value.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
In this case, we are binding the callback's this
to the value of MyConstructor
's this
.
Note: When binding context for jQuery, use jQuery.proxy
[docs] instead. The reason to do this is so that you don't need to store the reference to the function when unbinding an event callback. jQuery handles that internally.
ECMAScript 6: Use arrow functions
ECMAScript 6 introduces arrow functions, which can be thought of as lambda functions. They don't have their own this
binding. Instead, this
is looked up in scope just like a normal variable. That means you don't have to call .bind
. That's not the only special behaviour they have, please refer to the MDN documentation for more information.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
Set this
of the callback - part 2
Some functions/methods which accept callbacks also accept a value to which the callback's this
should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map
[docs] is such a method. Its signature is:
array.map(callback[, thisArg])
The first argument is the callback and the second argument is the value this
should refer to. Here is a contrived example:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Note: Whether or not you can pass a value for this
is usually mentioned in the documentation of that function/method. For example, jQuery's $.ajax
method [docs] describes an option called context
:
This object will be made the context of all Ajax-related callbacks.
Common problem: Using object methods as callbacks/event handlers
Another common manifestation of this problem is when an object method is used as callback/event handler. Functions are first-class citizens in JavaScript and the term "method" is just a colloquial term for a function that is a value of an object property. But that function doesn't have a specific link to its "containing" object.
Consider the following example:
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = function() {
console.log(this.data);
};
The function this.method
is assigned as click event handler, but if the document.body
is clicked, the value logged will be undefined
, because inside the event handler, this
refers to the document.body
, not the instance of Foo
.
As already mentioned at the beginning, what this
refers to depends on how the function is called, not how it is defined.
If the code was like the following, it might be more obvious that the function doesn't have an implicit reference to the object:
function method() {
console.log(this.data);
}
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = method;
The solution is the same as mentioned above: If available, use .bind
to explicitly bind this
to a specific value
document.body.onclick = this.method.bind(this);
or explicitly call the function as a "method" of the object, by using an anonymous function as callback / event handler and assign the object (this
) to another variable:
var self = this;
document.body.onclick = function() {
self.method();
};
or use an arrow function:
document.body.onclick = () => this.method();
25
Felix, I've read to this answer before but never replied. I grow concerned that people useself
andthat
to refer tothis
. I feel this way becausethis
is an overloaded variable used in different contexts; whereasself
usually corresponds to the local instance andthat
usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use_this
, but am not sure how others feel, except for the non-uniform practice that has resulted.
– vol7ron
Sep 12 '14 at 15:39
1
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that?
– andig
Dec 28 '15 at 15:57
3
@FelixKling It can be useful at times to rely onFunction.prototype.call ()
andFunction.prototype.apply ()
. Particularly withapply ()
I've gotten a lot of mileage. I am less inclined to usebind ()
perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options.
– Nolo
Nov 15 '16 at 6:02
2
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all.
– Aluan Haddad
Feb 12 '17 at 12:53
1
re arrow functions "Instead, this is looked up in scope just like a normal variable." totally made this click for me, thank you!() => this.clicked()
;)
– alphanumeric0101
May 25 at 20:36
|
show 10 more comments
up vote
155
down vote
Here are several ways to access parent context inside child context -
- You can use
bind()
function. - Store reference to context/this inside another variable(see below example).
- Use ES6 Arrow functions.
- Alter code/function design/architecture - for this you should have command over design patterns in javascript.
1. Use bind()
function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
If you are using underscore.js
- http://underscorejs.org/#bind
transport.on('data', _.bind(function () {
alert(this.data);
}, this));
2 Store reference to context/this inside another variable
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
3 Arrow function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
add a comment |
up vote
39
down vote
It's all in the "magic" syntax of calling a method:
object.property();
When you get the property from the object and call it in one go, the object will be the context for the method. If you call the same method, but in separate steps, the context is the global scope (window) instead:
var f = object.property;
f();
When you get the reference of a method, it's no longer attached to the object, it's just a reference to a plain function. The same happens when you get the reference to use as a callback:
this.saveNextLevelData(this.setAll);
That's where you would bind the context to the function:
this.saveNextLevelData(this.setAll.bind(this));
If you are using jQuery you should use the $.proxy
method instead, as bind
is not supported in all browsers:
this.saveNextLevelData($.proxy(this.setAll, this));
add a comment |
up vote
21
down vote
The trouble with "context"
The term "context" is sometimes used to refer to the object referenced by this. Its use is inappropriate because it doesn't fit either semantically or technically with ECMAScript's this.
"Context" means the circumstances surrounding something that adds meaning, or some preceding and following information that gives extra meaning. The term "context" is used in ECMAScript to refer to execution context, which is all the parameters, scope and this within the scope of some executing code.
This is shown in ECMA-262 section 10.4.2:
Set the ThisBinding to the same value as the ThisBinding of the
calling execution context
which clearly indicates that this is part of an execution context.
An execution context provides the surrounding information that adds meaning to code that is being executed. It includes much more information that just the thisBinding.
So the value of this isn't "context", it's just one part of an execution context. It's essentially a local variable that can be set by the call to any object and in strict mode, to any value at all.
add a comment |
up vote
16
down vote
First, you need to have a clear understanding of scope
and behaviour of this
keyword in the context of scope
.
this
& scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
in short, global scope refers to the window object.Variables declared in a global scope are accessible from anywhere.On the other hand function scope resides inside of a function.variable declared inside a function cannot be accessed from outside world normally.this
keyword in global scope refers to the window object.this
inside function also refers to the window object.So this
will always refer to the window until we find a way to manipulate this
to indicate a context of our own choosing.
--------------------------------------------------------------------------------
- -
- Global Scope -
- ( globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // outer function scope -
- // inside outer function"this" keyword refers to window object - -
- callback() // "this" inside callback also refers window object -
- } -
- -
- function callback_function(){ -
- -
- // function to be passed as callback -
- -
- // here "THIS" refers to window object also -
- -
- } -
- -
- outer_function(callback_function) -
- // invoke with callback -
--------------------------------------------------------------------------------
Different ways to manipulate this
inside callback functions:
Here I have a constructor function called Person. It has a property called name
and four method called sayNameVersion1
,sayNameVersion2
,sayNameVersion3
,sayNameVersion4
. All four of them has one specific task.Accept a callback and invoke it.The callback has a specific task which is to log the name property of an instance of Person constructor function.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// function to be used as callback
var parentObject = this
console.log(parentObject)
}
Now let's create an instance from person constructor and invoke different versions of sayNameVersionX
( X refers to 1,2,3,4 ) method with niceCallback
to see how many ways we can manipulate the this
inside callback to refer to the person
instance.
var p1 = new Person('zami') // create an instance of Person constructor
bind :
What bind do is to create a new function with the this
keyword set to the provided value.
sayNameVersion1
and sayNameVersion2
use bind to manipulate this
of the callback function.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
first one bind this
with callback inside the method itself.And for the second one callback is passed with the object bound to it.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
call :
The first argument
of the call
method is used as this
inside the function that is invoked with call
attached to it.
sayNameVersion3
uses call
to manipulate the this
to refer to the person object that we created, instead of the window object.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
and it is called like the following :
p1.sayNameVersion3(niceCallback)
apply :
Similar to call
, first argument of apply
refers to the object that will be indicated by this
keyword.
sayNameVersion4
uses apply
to manipulate this
to refer to person object
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
and it is called like the following.Simply the callback is passed,
p1.sayNameVersion4(niceCallback)
any constructive criticism regarding the answer will be appreciated !
– AL-zami
Aug 19 '17 at 8:55
The this keyword in the global scope doesn't necessarily refer to the window object. That is true only in a browser.
– Randall Flagg
May 23 at 10:04
@RandallFlagg i wrote this answer from a browser's perspective.Fell free to inhance this answer if necessary :)
– AL-zami
Jul 9 at 0:14
add a comment |
up vote
13
down vote
We can not bind this to setTimeout()
, as it always execute with global object (Window), if you want to access this
context in the callback function then by using bind()
to the callback function we can achieve as:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
5
How is this different than any of the existing answers?
– Felix Kling
Nov 17 '17 at 15:17
add a comment |
up vote
2
down vote
Another approach, which is the standard way since DOM2 to bind this
within the event listener, that let you always remove the listener (among other benefits), is the handleEvent(evt)
method from the EventListener
interface:
var obj = {
handleEvent(e) {
// always true
console.log(this === obj);
}
};
document.body.addEventListener('click', obj);
Detailed information about using handleEvent
can be found here: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
add a comment |
up vote
0
down vote
Currently there is another approach possible if classes are used in code.
With support of class fields it's possible to make it next way:
class someView {
onSomeInputKeyUp = (event) => {
console.log(this); // this refers to correct value
// ....
someInitMethod() {
//...
someInput.addEventListener('input', this.onSomeInputKeyUp)
For sure under the hood it's all old good arrow function that bind context but in this form it looks much more clear that explicit binding.
Since it's Stage 3 Proposal you will need babel and appropriate babel plugin to process it as for now(08/2018).
add a comment |
protected by Samuel Liew♦ Oct 5 '15 at 8:59
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
8 Answers
8
active
oldest
votes
8 Answers
8
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1352
down vote
accepted
What you should know about this
this
(aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scopes like other variables (except for arrow functions, see below). Here are some examples:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
To learn more about this
, have a look at the MDN documentation.
How to refer to the correct this
Don't use this
You actually don't want to access this
in particular, but the object it refers to. That's why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self
and that
.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Since self
is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that you can access the this
value of the callback itself.
Explicitly set this
of the callback - part 1
It might look like you have no control over the value of this
because its value is set automatically, but that is actually not the case.
Every function has the method .bind
[docs], which returns a new function with this
bound to a value. The function has exactly the same behaviour as the one you called .bind
on, only that this
was set by you. No matter how or when that function is called, this
will always refer to the passed value.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
In this case, we are binding the callback's this
to the value of MyConstructor
's this
.
Note: When binding context for jQuery, use jQuery.proxy
[docs] instead. The reason to do this is so that you don't need to store the reference to the function when unbinding an event callback. jQuery handles that internally.
ECMAScript 6: Use arrow functions
ECMAScript 6 introduces arrow functions, which can be thought of as lambda functions. They don't have their own this
binding. Instead, this
is looked up in scope just like a normal variable. That means you don't have to call .bind
. That's not the only special behaviour they have, please refer to the MDN documentation for more information.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
Set this
of the callback - part 2
Some functions/methods which accept callbacks also accept a value to which the callback's this
should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map
[docs] is such a method. Its signature is:
array.map(callback[, thisArg])
The first argument is the callback and the second argument is the value this
should refer to. Here is a contrived example:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Note: Whether or not you can pass a value for this
is usually mentioned in the documentation of that function/method. For example, jQuery's $.ajax
method [docs] describes an option called context
:
This object will be made the context of all Ajax-related callbacks.
Common problem: Using object methods as callbacks/event handlers
Another common manifestation of this problem is when an object method is used as callback/event handler. Functions are first-class citizens in JavaScript and the term "method" is just a colloquial term for a function that is a value of an object property. But that function doesn't have a specific link to its "containing" object.
Consider the following example:
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = function() {
console.log(this.data);
};
The function this.method
is assigned as click event handler, but if the document.body
is clicked, the value logged will be undefined
, because inside the event handler, this
refers to the document.body
, not the instance of Foo
.
As already mentioned at the beginning, what this
refers to depends on how the function is called, not how it is defined.
If the code was like the following, it might be more obvious that the function doesn't have an implicit reference to the object:
function method() {
console.log(this.data);
}
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = method;
The solution is the same as mentioned above: If available, use .bind
to explicitly bind this
to a specific value
document.body.onclick = this.method.bind(this);
or explicitly call the function as a "method" of the object, by using an anonymous function as callback / event handler and assign the object (this
) to another variable:
var self = this;
document.body.onclick = function() {
self.method();
};
or use an arrow function:
document.body.onclick = () => this.method();
25
Felix, I've read to this answer before but never replied. I grow concerned that people useself
andthat
to refer tothis
. I feel this way becausethis
is an overloaded variable used in different contexts; whereasself
usually corresponds to the local instance andthat
usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use_this
, but am not sure how others feel, except for the non-uniform practice that has resulted.
– vol7ron
Sep 12 '14 at 15:39
1
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that?
– andig
Dec 28 '15 at 15:57
3
@FelixKling It can be useful at times to rely onFunction.prototype.call ()
andFunction.prototype.apply ()
. Particularly withapply ()
I've gotten a lot of mileage. I am less inclined to usebind ()
perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options.
– Nolo
Nov 15 '16 at 6:02
2
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all.
– Aluan Haddad
Feb 12 '17 at 12:53
1
re arrow functions "Instead, this is looked up in scope just like a normal variable." totally made this click for me, thank you!() => this.clicked()
;)
– alphanumeric0101
May 25 at 20:36
|
show 10 more comments
up vote
1352
down vote
accepted
What you should know about this
this
(aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scopes like other variables (except for arrow functions, see below). Here are some examples:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
To learn more about this
, have a look at the MDN documentation.
How to refer to the correct this
Don't use this
You actually don't want to access this
in particular, but the object it refers to. That's why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self
and that
.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Since self
is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that you can access the this
value of the callback itself.
Explicitly set this
of the callback - part 1
It might look like you have no control over the value of this
because its value is set automatically, but that is actually not the case.
Every function has the method .bind
[docs], which returns a new function with this
bound to a value. The function has exactly the same behaviour as the one you called .bind
on, only that this
was set by you. No matter how or when that function is called, this
will always refer to the passed value.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
In this case, we are binding the callback's this
to the value of MyConstructor
's this
.
Note: When binding context for jQuery, use jQuery.proxy
[docs] instead. The reason to do this is so that you don't need to store the reference to the function when unbinding an event callback. jQuery handles that internally.
ECMAScript 6: Use arrow functions
ECMAScript 6 introduces arrow functions, which can be thought of as lambda functions. They don't have their own this
binding. Instead, this
is looked up in scope just like a normal variable. That means you don't have to call .bind
. That's not the only special behaviour they have, please refer to the MDN documentation for more information.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
Set this
of the callback - part 2
Some functions/methods which accept callbacks also accept a value to which the callback's this
should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map
[docs] is such a method. Its signature is:
array.map(callback[, thisArg])
The first argument is the callback and the second argument is the value this
should refer to. Here is a contrived example:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Note: Whether or not you can pass a value for this
is usually mentioned in the documentation of that function/method. For example, jQuery's $.ajax
method [docs] describes an option called context
:
This object will be made the context of all Ajax-related callbacks.
Common problem: Using object methods as callbacks/event handlers
Another common manifestation of this problem is when an object method is used as callback/event handler. Functions are first-class citizens in JavaScript and the term "method" is just a colloquial term for a function that is a value of an object property. But that function doesn't have a specific link to its "containing" object.
Consider the following example:
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = function() {
console.log(this.data);
};
The function this.method
is assigned as click event handler, but if the document.body
is clicked, the value logged will be undefined
, because inside the event handler, this
refers to the document.body
, not the instance of Foo
.
As already mentioned at the beginning, what this
refers to depends on how the function is called, not how it is defined.
If the code was like the following, it might be more obvious that the function doesn't have an implicit reference to the object:
function method() {
console.log(this.data);
}
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = method;
The solution is the same as mentioned above: If available, use .bind
to explicitly bind this
to a specific value
document.body.onclick = this.method.bind(this);
or explicitly call the function as a "method" of the object, by using an anonymous function as callback / event handler and assign the object (this
) to another variable:
var self = this;
document.body.onclick = function() {
self.method();
};
or use an arrow function:
document.body.onclick = () => this.method();
25
Felix, I've read to this answer before but never replied. I grow concerned that people useself
andthat
to refer tothis
. I feel this way becausethis
is an overloaded variable used in different contexts; whereasself
usually corresponds to the local instance andthat
usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use_this
, but am not sure how others feel, except for the non-uniform practice that has resulted.
– vol7ron
Sep 12 '14 at 15:39
1
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that?
– andig
Dec 28 '15 at 15:57
3
@FelixKling It can be useful at times to rely onFunction.prototype.call ()
andFunction.prototype.apply ()
. Particularly withapply ()
I've gotten a lot of mileage. I am less inclined to usebind ()
perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options.
– Nolo
Nov 15 '16 at 6:02
2
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all.
– Aluan Haddad
Feb 12 '17 at 12:53
1
re arrow functions "Instead, this is looked up in scope just like a normal variable." totally made this click for me, thank you!() => this.clicked()
;)
– alphanumeric0101
May 25 at 20:36
|
show 10 more comments
up vote
1352
down vote
accepted
up vote
1352
down vote
accepted
What you should know about this
this
(aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scopes like other variables (except for arrow functions, see below). Here are some examples:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
To learn more about this
, have a look at the MDN documentation.
How to refer to the correct this
Don't use this
You actually don't want to access this
in particular, but the object it refers to. That's why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self
and that
.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Since self
is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that you can access the this
value of the callback itself.
Explicitly set this
of the callback - part 1
It might look like you have no control over the value of this
because its value is set automatically, but that is actually not the case.
Every function has the method .bind
[docs], which returns a new function with this
bound to a value. The function has exactly the same behaviour as the one you called .bind
on, only that this
was set by you. No matter how or when that function is called, this
will always refer to the passed value.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
In this case, we are binding the callback's this
to the value of MyConstructor
's this
.
Note: When binding context for jQuery, use jQuery.proxy
[docs] instead. The reason to do this is so that you don't need to store the reference to the function when unbinding an event callback. jQuery handles that internally.
ECMAScript 6: Use arrow functions
ECMAScript 6 introduces arrow functions, which can be thought of as lambda functions. They don't have their own this
binding. Instead, this
is looked up in scope just like a normal variable. That means you don't have to call .bind
. That's not the only special behaviour they have, please refer to the MDN documentation for more information.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
Set this
of the callback - part 2
Some functions/methods which accept callbacks also accept a value to which the callback's this
should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map
[docs] is such a method. Its signature is:
array.map(callback[, thisArg])
The first argument is the callback and the second argument is the value this
should refer to. Here is a contrived example:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Note: Whether or not you can pass a value for this
is usually mentioned in the documentation of that function/method. For example, jQuery's $.ajax
method [docs] describes an option called context
:
This object will be made the context of all Ajax-related callbacks.
Common problem: Using object methods as callbacks/event handlers
Another common manifestation of this problem is when an object method is used as callback/event handler. Functions are first-class citizens in JavaScript and the term "method" is just a colloquial term for a function that is a value of an object property. But that function doesn't have a specific link to its "containing" object.
Consider the following example:
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = function() {
console.log(this.data);
};
The function this.method
is assigned as click event handler, but if the document.body
is clicked, the value logged will be undefined
, because inside the event handler, this
refers to the document.body
, not the instance of Foo
.
As already mentioned at the beginning, what this
refers to depends on how the function is called, not how it is defined.
If the code was like the following, it might be more obvious that the function doesn't have an implicit reference to the object:
function method() {
console.log(this.data);
}
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = method;
The solution is the same as mentioned above: If available, use .bind
to explicitly bind this
to a specific value
document.body.onclick = this.method.bind(this);
or explicitly call the function as a "method" of the object, by using an anonymous function as callback / event handler and assign the object (this
) to another variable:
var self = this;
document.body.onclick = function() {
self.method();
};
or use an arrow function:
document.body.onclick = () => this.method();
What you should know about this
this
(aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scopes like other variables (except for arrow functions, see below). Here are some examples:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
To learn more about this
, have a look at the MDN documentation.
How to refer to the correct this
Don't use this
You actually don't want to access this
in particular, but the object it refers to. That's why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self
and that
.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Since self
is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that you can access the this
value of the callback itself.
Explicitly set this
of the callback - part 1
It might look like you have no control over the value of this
because its value is set automatically, but that is actually not the case.
Every function has the method .bind
[docs], which returns a new function with this
bound to a value. The function has exactly the same behaviour as the one you called .bind
on, only that this
was set by you. No matter how or when that function is called, this
will always refer to the passed value.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
In this case, we are binding the callback's this
to the value of MyConstructor
's this
.
Note: When binding context for jQuery, use jQuery.proxy
[docs] instead. The reason to do this is so that you don't need to store the reference to the function when unbinding an event callback. jQuery handles that internally.
ECMAScript 6: Use arrow functions
ECMAScript 6 introduces arrow functions, which can be thought of as lambda functions. They don't have their own this
binding. Instead, this
is looked up in scope just like a normal variable. That means you don't have to call .bind
. That's not the only special behaviour they have, please refer to the MDN documentation for more information.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
Set this
of the callback - part 2
Some functions/methods which accept callbacks also accept a value to which the callback's this
should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map
[docs] is such a method. Its signature is:
array.map(callback[, thisArg])
The first argument is the callback and the second argument is the value this
should refer to. Here is a contrived example:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Note: Whether or not you can pass a value for this
is usually mentioned in the documentation of that function/method. For example, jQuery's $.ajax
method [docs] describes an option called context
:
This object will be made the context of all Ajax-related callbacks.
Common problem: Using object methods as callbacks/event handlers
Another common manifestation of this problem is when an object method is used as callback/event handler. Functions are first-class citizens in JavaScript and the term "method" is just a colloquial term for a function that is a value of an object property. But that function doesn't have a specific link to its "containing" object.
Consider the following example:
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = function() {
console.log(this.data);
};
The function this.method
is assigned as click event handler, but if the document.body
is clicked, the value logged will be undefined
, because inside the event handler, this
refers to the document.body
, not the instance of Foo
.
As already mentioned at the beginning, what this
refers to depends on how the function is called, not how it is defined.
If the code was like the following, it might be more obvious that the function doesn't have an implicit reference to the object:
function method() {
console.log(this.data);
}
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = method;
The solution is the same as mentioned above: If available, use .bind
to explicitly bind this
to a specific value
document.body.onclick = this.method.bind(this);
or explicitly call the function as a "method" of the object, by using an anonymous function as callback / event handler and assign the object (this
) to another variable:
var self = this;
document.body.onclick = function() {
self.method();
};
or use an arrow function:
document.body.onclick = () => this.method();
edited Aug 16 at 4:03
answered Nov 29 '13 at 6:13
Felix Kling
539k123842892
539k123842892
25
Felix, I've read to this answer before but never replied. I grow concerned that people useself
andthat
to refer tothis
. I feel this way becausethis
is an overloaded variable used in different contexts; whereasself
usually corresponds to the local instance andthat
usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use_this
, but am not sure how others feel, except for the non-uniform practice that has resulted.
– vol7ron
Sep 12 '14 at 15:39
1
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that?
– andig
Dec 28 '15 at 15:57
3
@FelixKling It can be useful at times to rely onFunction.prototype.call ()
andFunction.prototype.apply ()
. Particularly withapply ()
I've gotten a lot of mileage. I am less inclined to usebind ()
perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options.
– Nolo
Nov 15 '16 at 6:02
2
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all.
– Aluan Haddad
Feb 12 '17 at 12:53
1
re arrow functions "Instead, this is looked up in scope just like a normal variable." totally made this click for me, thank you!() => this.clicked()
;)
– alphanumeric0101
May 25 at 20:36
|
show 10 more comments
25
Felix, I've read to this answer before but never replied. I grow concerned that people useself
andthat
to refer tothis
. I feel this way becausethis
is an overloaded variable used in different contexts; whereasself
usually corresponds to the local instance andthat
usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use_this
, but am not sure how others feel, except for the non-uniform practice that has resulted.
– vol7ron
Sep 12 '14 at 15:39
1
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that?
– andig
Dec 28 '15 at 15:57
3
@FelixKling It can be useful at times to rely onFunction.prototype.call ()
andFunction.prototype.apply ()
. Particularly withapply ()
I've gotten a lot of mileage. I am less inclined to usebind ()
perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options.
– Nolo
Nov 15 '16 at 6:02
2
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all.
– Aluan Haddad
Feb 12 '17 at 12:53
1
re arrow functions "Instead, this is looked up in scope just like a normal variable." totally made this click for me, thank you!() => this.clicked()
;)
– alphanumeric0101
May 25 at 20:36
25
25
Felix, I've read to this answer before but never replied. I grow concerned that people use
self
and that
to refer to this
. I feel this way because this
is an overloaded variable used in different contexts; whereas self
usually corresponds to the local instance and that
usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use _this
, but am not sure how others feel, except for the non-uniform practice that has resulted.– vol7ron
Sep 12 '14 at 15:39
Felix, I've read to this answer before but never replied. I grow concerned that people use
self
and that
to refer to this
. I feel this way because this
is an overloaded variable used in different contexts; whereas self
usually corresponds to the local instance and that
usually refers to another object. I know you did not set this rule, as I've seen it appear in a number of other places, but it is also why I've started to use _this
, but am not sure how others feel, except for the non-uniform practice that has resulted.– vol7ron
Sep 12 '14 at 15:39
1
1
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that?
– andig
Dec 28 '15 at 15:57
@FelixKling would it be safe to assume that using this inside prototype functions will always have the expected behaviour regardless how they are (typically) called? When using callbacks inside prototype functions, is there an alternative to bind(), self or that?
– andig
Dec 28 '15 at 15:57
3
3
@FelixKling It can be useful at times to rely on
Function.prototype.call ()
and Function.prototype.apply ()
. Particularly with apply ()
I've gotten a lot of mileage. I am less inclined to use bind ()
perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options.– Nolo
Nov 15 '16 at 6:02
@FelixKling It can be useful at times to rely on
Function.prototype.call ()
and Function.prototype.apply ()
. Particularly with apply ()
I've gotten a lot of mileage. I am less inclined to use bind ()
perhaps only out of habit though I am aware ( but not certain ) that there may be slight overhead advantages to using bind over the other options.– Nolo
Nov 15 '16 at 6:02
2
2
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all.
– Aluan Haddad
Feb 12 '17 at 12:53
Great answer but consider adding an additional optional solution which is just to not use classes, new, or this at all.
– Aluan Haddad
Feb 12 '17 at 12:53
1
1
re arrow functions "Instead, this is looked up in scope just like a normal variable." totally made this click for me, thank you!
() => this.clicked()
;)– alphanumeric0101
May 25 at 20:36
re arrow functions "Instead, this is looked up in scope just like a normal variable." totally made this click for me, thank you!
() => this.clicked()
;)– alphanumeric0101
May 25 at 20:36
|
show 10 more comments
up vote
155
down vote
Here are several ways to access parent context inside child context -
- You can use
bind()
function. - Store reference to context/this inside another variable(see below example).
- Use ES6 Arrow functions.
- Alter code/function design/architecture - for this you should have command over design patterns in javascript.
1. Use bind()
function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
If you are using underscore.js
- http://underscorejs.org/#bind
transport.on('data', _.bind(function () {
alert(this.data);
}, this));
2 Store reference to context/this inside another variable
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
3 Arrow function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
add a comment |
up vote
155
down vote
Here are several ways to access parent context inside child context -
- You can use
bind()
function. - Store reference to context/this inside another variable(see below example).
- Use ES6 Arrow functions.
- Alter code/function design/architecture - for this you should have command over design patterns in javascript.
1. Use bind()
function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
If you are using underscore.js
- http://underscorejs.org/#bind
transport.on('data', _.bind(function () {
alert(this.data);
}, this));
2 Store reference to context/this inside another variable
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
3 Arrow function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
add a comment |
up vote
155
down vote
up vote
155
down vote
Here are several ways to access parent context inside child context -
- You can use
bind()
function. - Store reference to context/this inside another variable(see below example).
- Use ES6 Arrow functions.
- Alter code/function design/architecture - for this you should have command over design patterns in javascript.
1. Use bind()
function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
If you are using underscore.js
- http://underscorejs.org/#bind
transport.on('data', _.bind(function () {
alert(this.data);
}, this));
2 Store reference to context/this inside another variable
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
3 Arrow function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
Here are several ways to access parent context inside child context -
- You can use
bind()
function. - Store reference to context/this inside another variable(see below example).
- Use ES6 Arrow functions.
- Alter code/function design/architecture - for this you should have command over design patterns in javascript.
1. Use bind()
function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', ( function () {
alert(this.data);
}).bind(this) );
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
If you are using underscore.js
- http://underscorejs.org/#bind
transport.on('data', _.bind(function () {
alert(this.data);
}, this));
2 Store reference to context/this inside another variable
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
3 Arrow function
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
edited Feb 20 at 9:43
answered Aug 13 '16 at 10:26
Mohan Dere
2,40411013
2,40411013
add a comment |
add a comment |
up vote
39
down vote
It's all in the "magic" syntax of calling a method:
object.property();
When you get the property from the object and call it in one go, the object will be the context for the method. If you call the same method, but in separate steps, the context is the global scope (window) instead:
var f = object.property;
f();
When you get the reference of a method, it's no longer attached to the object, it's just a reference to a plain function. The same happens when you get the reference to use as a callback:
this.saveNextLevelData(this.setAll);
That's where you would bind the context to the function:
this.saveNextLevelData(this.setAll.bind(this));
If you are using jQuery you should use the $.proxy
method instead, as bind
is not supported in all browsers:
this.saveNextLevelData($.proxy(this.setAll, this));
add a comment |
up vote
39
down vote
It's all in the "magic" syntax of calling a method:
object.property();
When you get the property from the object and call it in one go, the object will be the context for the method. If you call the same method, but in separate steps, the context is the global scope (window) instead:
var f = object.property;
f();
When you get the reference of a method, it's no longer attached to the object, it's just a reference to a plain function. The same happens when you get the reference to use as a callback:
this.saveNextLevelData(this.setAll);
That's where you would bind the context to the function:
this.saveNextLevelData(this.setAll.bind(this));
If you are using jQuery you should use the $.proxy
method instead, as bind
is not supported in all browsers:
this.saveNextLevelData($.proxy(this.setAll, this));
add a comment |
up vote
39
down vote
up vote
39
down vote
It's all in the "magic" syntax of calling a method:
object.property();
When you get the property from the object and call it in one go, the object will be the context for the method. If you call the same method, but in separate steps, the context is the global scope (window) instead:
var f = object.property;
f();
When you get the reference of a method, it's no longer attached to the object, it's just a reference to a plain function. The same happens when you get the reference to use as a callback:
this.saveNextLevelData(this.setAll);
That's where you would bind the context to the function:
this.saveNextLevelData(this.setAll.bind(this));
If you are using jQuery you should use the $.proxy
method instead, as bind
is not supported in all browsers:
this.saveNextLevelData($.proxy(this.setAll, this));
It's all in the "magic" syntax of calling a method:
object.property();
When you get the property from the object and call it in one go, the object will be the context for the method. If you call the same method, but in separate steps, the context is the global scope (window) instead:
var f = object.property;
f();
When you get the reference of a method, it's no longer attached to the object, it's just a reference to a plain function. The same happens when you get the reference to use as a callback:
this.saveNextLevelData(this.setAll);
That's where you would bind the context to the function:
this.saveNextLevelData(this.setAll.bind(this));
If you are using jQuery you should use the $.proxy
method instead, as bind
is not supported in all browsers:
this.saveNextLevelData($.proxy(this.setAll, this));
answered May 21 '14 at 0:11
Guffa
549k77552875
549k77552875
add a comment |
add a comment |
up vote
21
down vote
The trouble with "context"
The term "context" is sometimes used to refer to the object referenced by this. Its use is inappropriate because it doesn't fit either semantically or technically with ECMAScript's this.
"Context" means the circumstances surrounding something that adds meaning, or some preceding and following information that gives extra meaning. The term "context" is used in ECMAScript to refer to execution context, which is all the parameters, scope and this within the scope of some executing code.
This is shown in ECMA-262 section 10.4.2:
Set the ThisBinding to the same value as the ThisBinding of the
calling execution context
which clearly indicates that this is part of an execution context.
An execution context provides the surrounding information that adds meaning to code that is being executed. It includes much more information that just the thisBinding.
So the value of this isn't "context", it's just one part of an execution context. It's essentially a local variable that can be set by the call to any object and in strict mode, to any value at all.
add a comment |
up vote
21
down vote
The trouble with "context"
The term "context" is sometimes used to refer to the object referenced by this. Its use is inappropriate because it doesn't fit either semantically or technically with ECMAScript's this.
"Context" means the circumstances surrounding something that adds meaning, or some preceding and following information that gives extra meaning. The term "context" is used in ECMAScript to refer to execution context, which is all the parameters, scope and this within the scope of some executing code.
This is shown in ECMA-262 section 10.4.2:
Set the ThisBinding to the same value as the ThisBinding of the
calling execution context
which clearly indicates that this is part of an execution context.
An execution context provides the surrounding information that adds meaning to code that is being executed. It includes much more information that just the thisBinding.
So the value of this isn't "context", it's just one part of an execution context. It's essentially a local variable that can be set by the call to any object and in strict mode, to any value at all.
add a comment |
up vote
21
down vote
up vote
21
down vote
The trouble with "context"
The term "context" is sometimes used to refer to the object referenced by this. Its use is inappropriate because it doesn't fit either semantically or technically with ECMAScript's this.
"Context" means the circumstances surrounding something that adds meaning, or some preceding and following information that gives extra meaning. The term "context" is used in ECMAScript to refer to execution context, which is all the parameters, scope and this within the scope of some executing code.
This is shown in ECMA-262 section 10.4.2:
Set the ThisBinding to the same value as the ThisBinding of the
calling execution context
which clearly indicates that this is part of an execution context.
An execution context provides the surrounding information that adds meaning to code that is being executed. It includes much more information that just the thisBinding.
So the value of this isn't "context", it's just one part of an execution context. It's essentially a local variable that can be set by the call to any object and in strict mode, to any value at all.
The trouble with "context"
The term "context" is sometimes used to refer to the object referenced by this. Its use is inappropriate because it doesn't fit either semantically or technically with ECMAScript's this.
"Context" means the circumstances surrounding something that adds meaning, or some preceding and following information that gives extra meaning. The term "context" is used in ECMAScript to refer to execution context, which is all the parameters, scope and this within the scope of some executing code.
This is shown in ECMA-262 section 10.4.2:
Set the ThisBinding to the same value as the ThisBinding of the
calling execution context
which clearly indicates that this is part of an execution context.
An execution context provides the surrounding information that adds meaning to code that is being executed. It includes much more information that just the thisBinding.
So the value of this isn't "context", it's just one part of an execution context. It's essentially a local variable that can be set by the call to any object and in strict mode, to any value at all.
edited Aug 14 at 14:23
arcy
9,24743872
9,24743872
answered Jun 1 '14 at 0:44
RobG
96.1k19101143
96.1k19101143
add a comment |
add a comment |
up vote
16
down vote
First, you need to have a clear understanding of scope
and behaviour of this
keyword in the context of scope
.
this
& scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
in short, global scope refers to the window object.Variables declared in a global scope are accessible from anywhere.On the other hand function scope resides inside of a function.variable declared inside a function cannot be accessed from outside world normally.this
keyword in global scope refers to the window object.this
inside function also refers to the window object.So this
will always refer to the window until we find a way to manipulate this
to indicate a context of our own choosing.
--------------------------------------------------------------------------------
- -
- Global Scope -
- ( globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // outer function scope -
- // inside outer function"this" keyword refers to window object - -
- callback() // "this" inside callback also refers window object -
- } -
- -
- function callback_function(){ -
- -
- // function to be passed as callback -
- -
- // here "THIS" refers to window object also -
- -
- } -
- -
- outer_function(callback_function) -
- // invoke with callback -
--------------------------------------------------------------------------------
Different ways to manipulate this
inside callback functions:
Here I have a constructor function called Person. It has a property called name
and four method called sayNameVersion1
,sayNameVersion2
,sayNameVersion3
,sayNameVersion4
. All four of them has one specific task.Accept a callback and invoke it.The callback has a specific task which is to log the name property of an instance of Person constructor function.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// function to be used as callback
var parentObject = this
console.log(parentObject)
}
Now let's create an instance from person constructor and invoke different versions of sayNameVersionX
( X refers to 1,2,3,4 ) method with niceCallback
to see how many ways we can manipulate the this
inside callback to refer to the person
instance.
var p1 = new Person('zami') // create an instance of Person constructor
bind :
What bind do is to create a new function with the this
keyword set to the provided value.
sayNameVersion1
and sayNameVersion2
use bind to manipulate this
of the callback function.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
first one bind this
with callback inside the method itself.And for the second one callback is passed with the object bound to it.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
call :
The first argument
of the call
method is used as this
inside the function that is invoked with call
attached to it.
sayNameVersion3
uses call
to manipulate the this
to refer to the person object that we created, instead of the window object.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
and it is called like the following :
p1.sayNameVersion3(niceCallback)
apply :
Similar to call
, first argument of apply
refers to the object that will be indicated by this
keyword.
sayNameVersion4
uses apply
to manipulate this
to refer to person object
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
and it is called like the following.Simply the callback is passed,
p1.sayNameVersion4(niceCallback)
any constructive criticism regarding the answer will be appreciated !
– AL-zami
Aug 19 '17 at 8:55
The this keyword in the global scope doesn't necessarily refer to the window object. That is true only in a browser.
– Randall Flagg
May 23 at 10:04
@RandallFlagg i wrote this answer from a browser's perspective.Fell free to inhance this answer if necessary :)
– AL-zami
Jul 9 at 0:14
add a comment |
up vote
16
down vote
First, you need to have a clear understanding of scope
and behaviour of this
keyword in the context of scope
.
this
& scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
in short, global scope refers to the window object.Variables declared in a global scope are accessible from anywhere.On the other hand function scope resides inside of a function.variable declared inside a function cannot be accessed from outside world normally.this
keyword in global scope refers to the window object.this
inside function also refers to the window object.So this
will always refer to the window until we find a way to manipulate this
to indicate a context of our own choosing.
--------------------------------------------------------------------------------
- -
- Global Scope -
- ( globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // outer function scope -
- // inside outer function"this" keyword refers to window object - -
- callback() // "this" inside callback also refers window object -
- } -
- -
- function callback_function(){ -
- -
- // function to be passed as callback -
- -
- // here "THIS" refers to window object also -
- -
- } -
- -
- outer_function(callback_function) -
- // invoke with callback -
--------------------------------------------------------------------------------
Different ways to manipulate this
inside callback functions:
Here I have a constructor function called Person. It has a property called name
and four method called sayNameVersion1
,sayNameVersion2
,sayNameVersion3
,sayNameVersion4
. All four of them has one specific task.Accept a callback and invoke it.The callback has a specific task which is to log the name property of an instance of Person constructor function.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// function to be used as callback
var parentObject = this
console.log(parentObject)
}
Now let's create an instance from person constructor and invoke different versions of sayNameVersionX
( X refers to 1,2,3,4 ) method with niceCallback
to see how many ways we can manipulate the this
inside callback to refer to the person
instance.
var p1 = new Person('zami') // create an instance of Person constructor
bind :
What bind do is to create a new function with the this
keyword set to the provided value.
sayNameVersion1
and sayNameVersion2
use bind to manipulate this
of the callback function.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
first one bind this
with callback inside the method itself.And for the second one callback is passed with the object bound to it.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
call :
The first argument
of the call
method is used as this
inside the function that is invoked with call
attached to it.
sayNameVersion3
uses call
to manipulate the this
to refer to the person object that we created, instead of the window object.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
and it is called like the following :
p1.sayNameVersion3(niceCallback)
apply :
Similar to call
, first argument of apply
refers to the object that will be indicated by this
keyword.
sayNameVersion4
uses apply
to manipulate this
to refer to person object
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
and it is called like the following.Simply the callback is passed,
p1.sayNameVersion4(niceCallback)
any constructive criticism regarding the answer will be appreciated !
– AL-zami
Aug 19 '17 at 8:55
The this keyword in the global scope doesn't necessarily refer to the window object. That is true only in a browser.
– Randall Flagg
May 23 at 10:04
@RandallFlagg i wrote this answer from a browser's perspective.Fell free to inhance this answer if necessary :)
– AL-zami
Jul 9 at 0:14
add a comment |
up vote
16
down vote
up vote
16
down vote
First, you need to have a clear understanding of scope
and behaviour of this
keyword in the context of scope
.
this
& scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
in short, global scope refers to the window object.Variables declared in a global scope are accessible from anywhere.On the other hand function scope resides inside of a function.variable declared inside a function cannot be accessed from outside world normally.this
keyword in global scope refers to the window object.this
inside function also refers to the window object.So this
will always refer to the window until we find a way to manipulate this
to indicate a context of our own choosing.
--------------------------------------------------------------------------------
- -
- Global Scope -
- ( globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // outer function scope -
- // inside outer function"this" keyword refers to window object - -
- callback() // "this" inside callback also refers window object -
- } -
- -
- function callback_function(){ -
- -
- // function to be passed as callback -
- -
- // here "THIS" refers to window object also -
- -
- } -
- -
- outer_function(callback_function) -
- // invoke with callback -
--------------------------------------------------------------------------------
Different ways to manipulate this
inside callback functions:
Here I have a constructor function called Person. It has a property called name
and four method called sayNameVersion1
,sayNameVersion2
,sayNameVersion3
,sayNameVersion4
. All four of them has one specific task.Accept a callback and invoke it.The callback has a specific task which is to log the name property of an instance of Person constructor function.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// function to be used as callback
var parentObject = this
console.log(parentObject)
}
Now let's create an instance from person constructor and invoke different versions of sayNameVersionX
( X refers to 1,2,3,4 ) method with niceCallback
to see how many ways we can manipulate the this
inside callback to refer to the person
instance.
var p1 = new Person('zami') // create an instance of Person constructor
bind :
What bind do is to create a new function with the this
keyword set to the provided value.
sayNameVersion1
and sayNameVersion2
use bind to manipulate this
of the callback function.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
first one bind this
with callback inside the method itself.And for the second one callback is passed with the object bound to it.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
call :
The first argument
of the call
method is used as this
inside the function that is invoked with call
attached to it.
sayNameVersion3
uses call
to manipulate the this
to refer to the person object that we created, instead of the window object.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
and it is called like the following :
p1.sayNameVersion3(niceCallback)
apply :
Similar to call
, first argument of apply
refers to the object that will be indicated by this
keyword.
sayNameVersion4
uses apply
to manipulate this
to refer to person object
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
and it is called like the following.Simply the callback is passed,
p1.sayNameVersion4(niceCallback)
First, you need to have a clear understanding of scope
and behaviour of this
keyword in the context of scope
.
this
& scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
in short, global scope refers to the window object.Variables declared in a global scope are accessible from anywhere.On the other hand function scope resides inside of a function.variable declared inside a function cannot be accessed from outside world normally.this
keyword in global scope refers to the window object.this
inside function also refers to the window object.So this
will always refer to the window until we find a way to manipulate this
to indicate a context of our own choosing.
--------------------------------------------------------------------------------
- -
- Global Scope -
- ( globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // outer function scope -
- // inside outer function"this" keyword refers to window object - -
- callback() // "this" inside callback also refers window object -
- } -
- -
- function callback_function(){ -
- -
- // function to be passed as callback -
- -
- // here "THIS" refers to window object also -
- -
- } -
- -
- outer_function(callback_function) -
- // invoke with callback -
--------------------------------------------------------------------------------
Different ways to manipulate this
inside callback functions:
Here I have a constructor function called Person. It has a property called name
and four method called sayNameVersion1
,sayNameVersion2
,sayNameVersion3
,sayNameVersion4
. All four of them has one specific task.Accept a callback and invoke it.The callback has a specific task which is to log the name property of an instance of Person constructor function.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// function to be used as callback
var parentObject = this
console.log(parentObject)
}
Now let's create an instance from person constructor and invoke different versions of sayNameVersionX
( X refers to 1,2,3,4 ) method with niceCallback
to see how many ways we can manipulate the this
inside callback to refer to the person
instance.
var p1 = new Person('zami') // create an instance of Person constructor
bind :
What bind do is to create a new function with the this
keyword set to the provided value.
sayNameVersion1
and sayNameVersion2
use bind to manipulate this
of the callback function.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
first one bind this
with callback inside the method itself.And for the second one callback is passed with the object bound to it.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
call :
The first argument
of the call
method is used as this
inside the function that is invoked with call
attached to it.
sayNameVersion3
uses call
to manipulate the this
to refer to the person object that we created, instead of the window object.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
and it is called like the following :
p1.sayNameVersion3(niceCallback)
apply :
Similar to call
, first argument of apply
refers to the object that will be indicated by this
keyword.
sayNameVersion4
uses apply
to manipulate this
to refer to person object
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
and it is called like the following.Simply the callback is passed,
p1.sayNameVersion4(niceCallback)
edited Feb 19 at 21:01
mic4ael
3,79122033
3,79122033
answered Aug 18 '17 at 17:58
AL-zami
3,62053863
3,62053863
any constructive criticism regarding the answer will be appreciated !
– AL-zami
Aug 19 '17 at 8:55
The this keyword in the global scope doesn't necessarily refer to the window object. That is true only in a browser.
– Randall Flagg
May 23 at 10:04
@RandallFlagg i wrote this answer from a browser's perspective.Fell free to inhance this answer if necessary :)
– AL-zami
Jul 9 at 0:14
add a comment |
any constructive criticism regarding the answer will be appreciated !
– AL-zami
Aug 19 '17 at 8:55
The this keyword in the global scope doesn't necessarily refer to the window object. That is true only in a browser.
– Randall Flagg
May 23 at 10:04
@RandallFlagg i wrote this answer from a browser's perspective.Fell free to inhance this answer if necessary :)
– AL-zami
Jul 9 at 0:14
any constructive criticism regarding the answer will be appreciated !
– AL-zami
Aug 19 '17 at 8:55
any constructive criticism regarding the answer will be appreciated !
– AL-zami
Aug 19 '17 at 8:55
The this keyword in the global scope doesn't necessarily refer to the window object. That is true only in a browser.
– Randall Flagg
May 23 at 10:04
The this keyword in the global scope doesn't necessarily refer to the window object. That is true only in a browser.
– Randall Flagg
May 23 at 10:04
@RandallFlagg i wrote this answer from a browser's perspective.Fell free to inhance this answer if necessary :)
– AL-zami
Jul 9 at 0:14
@RandallFlagg i wrote this answer from a browser's perspective.Fell free to inhance this answer if necessary :)
– AL-zami
Jul 9 at 0:14
add a comment |
up vote
13
down vote
We can not bind this to setTimeout()
, as it always execute with global object (Window), if you want to access this
context in the callback function then by using bind()
to the callback function we can achieve as:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
5
How is this different than any of the existing answers?
– Felix Kling
Nov 17 '17 at 15:17
add a comment |
up vote
13
down vote
We can not bind this to setTimeout()
, as it always execute with global object (Window), if you want to access this
context in the callback function then by using bind()
to the callback function we can achieve as:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
5
How is this different than any of the existing answers?
– Felix Kling
Nov 17 '17 at 15:17
add a comment |
up vote
13
down vote
up vote
13
down vote
We can not bind this to setTimeout()
, as it always execute with global object (Window), if you want to access this
context in the callback function then by using bind()
to the callback function we can achieve as:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
We can not bind this to setTimeout()
, as it always execute with global object (Window), if you want to access this
context in the callback function then by using bind()
to the callback function we can achieve as:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
edited Apr 11 at 7:47
Aliaksandr Sushkevich
2,26041428
2,26041428
answered Nov 17 '17 at 14:32
Datta Chanewad
17717
17717
5
How is this different than any of the existing answers?
– Felix Kling
Nov 17 '17 at 15:17
add a comment |
5
How is this different than any of the existing answers?
– Felix Kling
Nov 17 '17 at 15:17
5
5
How is this different than any of the existing answers?
– Felix Kling
Nov 17 '17 at 15:17
How is this different than any of the existing answers?
– Felix Kling
Nov 17 '17 at 15:17
add a comment |
up vote
2
down vote
Another approach, which is the standard way since DOM2 to bind this
within the event listener, that let you always remove the listener (among other benefits), is the handleEvent(evt)
method from the EventListener
interface:
var obj = {
handleEvent(e) {
// always true
console.log(this === obj);
}
};
document.body.addEventListener('click', obj);
Detailed information about using handleEvent
can be found here: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
add a comment |
up vote
2
down vote
Another approach, which is the standard way since DOM2 to bind this
within the event listener, that let you always remove the listener (among other benefits), is the handleEvent(evt)
method from the EventListener
interface:
var obj = {
handleEvent(e) {
// always true
console.log(this === obj);
}
};
document.body.addEventListener('click', obj);
Detailed information about using handleEvent
can be found here: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
add a comment |
up vote
2
down vote
up vote
2
down vote
Another approach, which is the standard way since DOM2 to bind this
within the event listener, that let you always remove the listener (among other benefits), is the handleEvent(evt)
method from the EventListener
interface:
var obj = {
handleEvent(e) {
// always true
console.log(this === obj);
}
};
document.body.addEventListener('click', obj);
Detailed information about using handleEvent
can be found here: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
Another approach, which is the standard way since DOM2 to bind this
within the event listener, that let you always remove the listener (among other benefits), is the handleEvent(evt)
method from the EventListener
interface:
var obj = {
handleEvent(e) {
// always true
console.log(this === obj);
}
};
document.body.addEventListener('click', obj);
Detailed information about using handleEvent
can be found here: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
answered Aug 28 at 9:10
Andrea Puddu
34829
34829
add a comment |
add a comment |
up vote
0
down vote
Currently there is another approach possible if classes are used in code.
With support of class fields it's possible to make it next way:
class someView {
onSomeInputKeyUp = (event) => {
console.log(this); // this refers to correct value
// ....
someInitMethod() {
//...
someInput.addEventListener('input', this.onSomeInputKeyUp)
For sure under the hood it's all old good arrow function that bind context but in this form it looks much more clear that explicit binding.
Since it's Stage 3 Proposal you will need babel and appropriate babel plugin to process it as for now(08/2018).
add a comment |
up vote
0
down vote
Currently there is another approach possible if classes are used in code.
With support of class fields it's possible to make it next way:
class someView {
onSomeInputKeyUp = (event) => {
console.log(this); // this refers to correct value
// ....
someInitMethod() {
//...
someInput.addEventListener('input', this.onSomeInputKeyUp)
For sure under the hood it's all old good arrow function that bind context but in this form it looks much more clear that explicit binding.
Since it's Stage 3 Proposal you will need babel and appropriate babel plugin to process it as for now(08/2018).
add a comment |
up vote
0
down vote
up vote
0
down vote
Currently there is another approach possible if classes are used in code.
With support of class fields it's possible to make it next way:
class someView {
onSomeInputKeyUp = (event) => {
console.log(this); // this refers to correct value
// ....
someInitMethod() {
//...
someInput.addEventListener('input', this.onSomeInputKeyUp)
For sure under the hood it's all old good arrow function that bind context but in this form it looks much more clear that explicit binding.
Since it's Stage 3 Proposal you will need babel and appropriate babel plugin to process it as for now(08/2018).
Currently there is another approach possible if classes are used in code.
With support of class fields it's possible to make it next way:
class someView {
onSomeInputKeyUp = (event) => {
console.log(this); // this refers to correct value
// ....
someInitMethod() {
//...
someInput.addEventListener('input', this.onSomeInputKeyUp)
For sure under the hood it's all old good arrow function that bind context but in this form it looks much more clear that explicit binding.
Since it's Stage 3 Proposal you will need babel and appropriate babel plugin to process it as for now(08/2018).
answered Sep 22 at 13:38
skyboyer
3,07311028
3,07311028
add a comment |
add a comment |
protected by Samuel Liew♦ Oct 5 '15 at 8:59
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
57
From time to time I’m so fed up with a certain kind of question, that I decide to write a canonical answer. Even though these questions have been answered like a million times, it’s not always possible to find a good question + answer pair which is not “polluted” by irrelevant information. This is one of those moments and one of those questions (and I’m bored). If you think that there is actually a good existing canonical question/answer for this type of question, let me know and I will delete this one. Suggestions for improvements are welcome!
– Felix Kling
Nov 29 '13 at 6:13
Related: Preserving a reference to “this” in JavaScript prototype functions
– Bergi
Mar 1 '14 at 12:46
Related: “this” keyword in event methods when using JavaScript prototype object
– Bergi
Sep 9 '14 at 20:43
1
Useful TypeScript page about this, mostly applicable to JS too.
– Ondra Žižka
Feb 1 '17 at 21:49