How to correctly access `this` object in callback function
P粉608647033
2023-08-20 16:11:32
<p>I have a constructor that registers an event handler: </p>
<p><br /></p>
<pre class="snippet-code-js lang-js prettyprint-override"><code>function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
//Simulate transfer object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// Calling method
var obj = new MyConstructor('foo', transport);</code></pre>
<p><br /></p>
<p>However, within the callback function I cannot access the <code>data</code> properties of the created object. It seems that <code>this</code> does not point to the created object, but to another object. </p>
<p>I also tried using object methods instead of anonymous functions: </p>
<pre class="brush:php;toolbar:false;">function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};</pre>
<p>But it also had the same problem. </p>
<p>How do I access the correct object? </p>
The following are several ways to access the parent context in the child context:
bind()
function.1. Use
bind()
functionIf you use Underscore.js - http://underscorejs.org/#bind
2. Store the reference of context/this in another variable
3. Arrow function
Knowledge about
this
this
(also called "context") is a special keyword inside every function whose value depends only on how the function is called, not how it is defined. It is not affected by lexical scope, unlike other variables (except arrow functions, see below). Here are some examples:To learn more about
this
, please see the MDN documentation.How to quote the correct
this
Use arrow function
ECMAScript 6 introduced arrow functions, which can be thought of as lambda functions. They do not have their own
this
binding. Instead,this
is looked up in the scope, just like a normal variable. This means you don't need to call.bind
. They also have other special behaviors, see the MDN documentation for more information.Do not use
this
Actually, you don't need to access
this
specifically, but rather the object it refers to. So a simple solution is to create a new variable that also points to the object. Variables can have any name, but common ones areself
andthat
.Since
self
is a normal variable, it follows lexical scoping rules and can be accessed inside the callback function. This also has the advantage of having access to thethis
value of the callback function itself.Explicitly setting the callback function
this
- Part 1It may seem like you have no control over the value of
this
since its value is set automatically, but that's not actually the case.Each function has a method
.bind
[Documentation], which returns a method that willthis
New function bound to a value. This function behaves exactly like when you call.bind
, except thatthis
is set by you. No matter how or when the function is called,this
will always refer to the passed value.In this case, we bind the
this
of the callback function to thethis
value ofMyConstructor
.Note: For jQuery's binding context, use
jQuery.proxy
[Documentation]. The reason for this is that there is no need to store a reference to the function when unbinding the event callback. jQuery handles this internally.Setting the callback function
this
- Part 2Some functions/methods that accept a callback function also accept a value that should be used as
this
of the callback function. This is the same as manual binding, but the function/method performs the binding for you. For example,Array#map
[Documentation] is such a method. Its signature is:The first parameter is the callback function, and the second parameter is the value that
this
should reference. Here's a contrived example:Note: Whether the value of
this
can be passed is usually mentioned in the documentation of the function/method. For example, jQuery's$.ajax
method [Documentation] describes an option calledcontext
:FAQ: Using object methods as callbacks/event handlers
Another common manifestation of this problem is using object methods as callbacks/event handlers. In JavaScript, functions are first-class citizens, and the term "method" simply refers to a function that is the value of an object's property. But there is no specific link between the function and its "containing" object.
Consider the following example:
Function
this.method
is assigned as the click event handler, but ifdocument.body
is clicked, the recorded value will beundefined
because in the event Inside the handler,this
refers todocument.body
, not an instance ofFoo
.As mentioned before,
this
refers to how the function is called , not how is defined .It might be more obvious if the code looks like this:
Solution Same as mentioned above: use
if available.bind
to explicitly bindthis
to a specific valueOr by using an anonymous function as a callback/event