How to access the correct `this` inside a callback?


I have a constructor function which registers an event handler:





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:



but it exhibits the same problems.



How can I access the correct object?



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. Here are some examples:



To learn more about this, have a look at the MDN documentation.



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.



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.



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.



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 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.



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:



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 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.



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 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:



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 as callback / event handler and assign the object (this) to another variable:



or use an arrow function:



If you are using underscore.js - http://underscorejs.org/#bind



It's all in the "magic" syntax of calling a method:



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:



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:



That's where you would bind the context to the function:



If you are using jQuery you should use the $.proxy method instead, as bind is not supported in all browsers:



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.



First, you need to have a clear understanding of scope and behaviour of this keyword in the context of scope.



this & 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.



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.



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.



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.



first one bind this with callback inside the method itself.And for the second one callback is passed with the object bound to it.



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.



and it is called like the following :



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



and it is called like the following.Simply the callback is passed,



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:




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?

Popular posts from this blog

The Dalles, Oregon

眉山市

清晰法令