javascript tutorial - [Solved-5 Solutions] Access the correct ‘this’ inside a callback - javascript - java script - javascript array
Problem:
How to access the correct ‘this’ inside a callback?
Solution 1:
What we 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 scope, like other variables. Here are some examples:
To learn more about this, have a look at the MDN documentation .
How to refer to the correct this
Don't use this
We 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.
- Since self is a normal variable, it obeys lexical scope rules and is accessible inside the callback. This also has the advantage that we can access the this value of the callback itself.
- Explicitly set this of the callback - part 1
- It might look like we 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 behavior as the one we called .bind on, only that thiswas set by you. No matter how or when that function is called, this will always refer to the passed value.
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 we 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 we don't have to call .bind. That's not the only special behavior they have, please refer to the MDN documentation for more information.
- Set this of the callback - part 2
- Some functions/methods which accept callbacks also accept a value to which the callback's thisshould 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:
The first argument is the callback and the second argument is the value this should refer to. Here is a contrived example:
- Note: Whether or not we 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
- The function this.method is assigned as click event handler, but if the body is clicked, the value logged will be undefined, because inside the event handler, this refers to the 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:
The solution is the same as mentioned above: If available, use .bind to explicitly bind this to a specific value
or explicitly call the function as a "method" of the object, by using an anonymous function has callback / event handler and assign the object (this) to another variable:
or use an arrow function:
Solution 2:
Here are several ways to access parent context inside child context -
- We can use
bind()
function - - Store reference to context/this inside another variable
- Use ES6 Arrow functions -
- Alter code/function architecture - for this we should have commands on design patterns in javascript -
Use bind() function
If we are using underscore.js -
Store reference to context/this inside another variable
Arrow function
Solution 3:
It's all in the "magic" syntax of calling a method:
When we get the property from the object and call it in one go, the object will be the context for the method. If we call the same method, but in separate steps, the context is the global scope (window) instead:
When we 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 we get the reference to use as a callback:
That's where we would bind the context to the function:
If we are using jQuery we should use the $.proxy method instead, as bind is not supported in all browsers:
Solution 4:
The trouble with "context"
- The term "context" is sometimes used to refer to the object referenced by this. It's 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.
Solution 5:
The trouble with "context"
- The term "context" is sometimes used to refer to the object referenced by this. It's 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.