In the previous article Mastering JS " this
(a) inside, we learned how to correctly use the keyword in JavaScript this
and its basic principles. We also know this
that the key factor in deciding which object to point to is to find out the current execution context (execution context). But if the execution context is not set up in the normal way, the problem can become tricky. In this article, I'll focus on where this happens and how it can be remedied.
Troubleshoot common issues
In this section, we'll explore some of the most common issues with the This keyword and learn how to handle it.
1. Use in the method of disassembly (extracted)
this
The most common mistake is to assign the method of the object to a variable and assume that the function still points to the this
original object. We can see from the following example that this is not the case at all.
var car = { brand: "Nissan", getBrand: function(){ console.log(this.brand); }};var getCarBrand = car.getBrand;getCarBrand(); // output: undefined
It seems to be getCarBrand
quoted car.getBrand()
, but in fact he points to only getBrand()
himself. We already know that the most important thing in determining the context is the call point (Call-site), in the above code, the call point is getCarBrand()
, this is just a normal function call.
getCarBrand
the method that proves pointing to a normal function (baseless function, which is not bound to any particular object) is used alert(getCarBrand);
to view the corresponding content, and the output of alert is as follows:
function(){ console.log(this.brand);}
getCarBrand
Just a normal function, it is no longer the car
object's method. So, in this case, it this.brand
will actually be converted to window.brand
. The result of the output is of course undefined
.
If we remove a method from an object (extract), then this method becomes a normal function. His connection to the original object was cut off (severed), so no longer works as it was. In other words, a detached function is no longer bound to the original object.
How do we deal with this situation? OK, if you want to point to the original object, you need to getCarBrand
explicitly getBrand()
bind the function (BIND) to the object when assigning it, and car
of course we can use the bind () method.
var getCarBrand = car.getBrand.bind(car);getCarBrand(); // output: Nissan
Now we have the expected correct output as we successfully redefine the desired context.
2. Use in callback functions
this
The second type of problem is the use of a (used this
) method as a callback function. For example:
<button id="btn" type="button">查看汽车品牌</button>
var car = { brand: "Nissan", getBrand: function(){ console.log(this.brand); }};var el = document.getElementById("btn");el.addEventListener("click", car.getBrand);
Although it is used car.getBrand
, it is actually just getBrand()
associating the function to the button
object.
Passing parameters to a function is an implicit assignment, so this is basically the same as the previous example. The difference is that car.getBrand
no value is explicitly assigned at this time. The result is the same, get just a normal function, the bound object is button
.
In other words, when we execute a method on an object, although the method may be defined within another object, the this
keyword no longer points to the original object, but instead points to the object that called the method.
In the example above: we use (that is, the el
button) to execute car.getBrand
, but not the car
object, although it was originally defined in the car
object. So, the this
point is el
, instead of car
.
If you do need to keep a reference to the original object, you need to explicitly getBrand()
bind the function to the car
object, and you can use the methods that each function has bind()
.
el.addEventListener("click", car.getBrand.bind(car));
Now, you can run it the way you want.
3. Use in closures (Closure)
this
Use in closures can this
also cause errors. Look at the following example:
var car = { brand: "Nissan", getBrand: function(){ var closure = function(){ console.log(this.brand); }; return closure(); }};car.getBrand(); // output: undefined
Here, the output we get is undefined
because the closure function (that is, the intrinsic function) cannot access the variables of the external function this
. So the end result is this.brand
equivalent window.brand
, because the inner function this
is bound to a global object.
For this problem, we can this
bind to the getBrand()
function.
var car = { brand: "Nissan", getBrand: function(){ var closure = function(){ console.log(this.brand); }.bind(this);// 注意这里 return closure(); }};car.getBrand(); // output: Nissan
The bindings here are equivalent car.getBrand.bind(car)
.
Another common way to deal with closures is to assign a this
value to another variable to avoid unnecessary changes.
var car = { brand: "Nissan", getBrand: function(){ var self = this; var closure = function(){ console.log(self.brand); }; return closure(); }};car.getBrand(); // output: Nissan
Here, we can assign the _this value,,,,, and so _this
that
on, self
me
my
context
or other variable names that have this kind of meaning. The key is to preserve the lower outer object reference.
High-Tech in ECMAScript 6
In the example above, we see the use of "syntactic formality this
," which means that we can assign a this
value to another variable. In ECMAScript 6 We can use the more elegant new technique, arrow function, to achieve a similar effect.
Arrow-functions is not function
created by the keyword, but by the so-called "fat Arrow" operator (fat Arrow =>
). Unlike the general function, the arrow function takes a value from its enclosing range (enclosing scope) this
. The syntax bindings for the arrow functions are not overwritten, even if the new operator is used.
Let's take a look at how the arrow functions replace var self = this;
this statement:
var car = { brand: "Nissan", getBrand: function(){ // 箭头函数保留了语法上的 "this" 作用域. var closure = () => { console.log(this.brand); }; return closure(); }};car.getBrand(); // output: Nissan
About
this
The Knowledge point
As with other mechanisms, this
keywords follow a few simple rules, and if you know the rules, you can use them more smoothly. The following is a quick review of the knowledge points learned in these two sections:
- The global object is pointed to in the following cases
this
:
- In the outermost code, not in any function.
- Functions that are not object methods (method)
- is not a constructor (constructor) function inside
- When a function is called as a property of the parent object,
this
the parent object is pointed to.
- When a function passes
call()
, apply()
or bind()
is called, this
it points to the first argument passed to these methods. If the first parameter is anull
- Or is not an object, then
this
the global object is pointed to.
new
when you use an operator to invoke a function, this
it points to the newly created object.
- When you use the arrow function in ECMAScript 6, you
this
point to the Ancestor object (parent object) According to the scope of the syntax you are at.
With these simple and straightforward rules in hand, we can easily see this
which object is pointing, and if it does, it can be done with the black technology we've learned.
Summarize
Mastering JavaScript this
is not easy, but if you use it enough, you will naturally understand it. Hopefully this series of blogs will help you lay the groundwork and deepen your understanding, and then you'll have a good idea of the next time you have a problem.
Recommended Reading
Nanyi Teacher: ECMAScript 6 Getting Started
Some learning summaries of cnblog:javascript context and scope
Infoq: ES6 (1~10) series
babeljs-es6:https://babeljs.io/repl/
Master JS in the " this
" (a)
Master js " this
" (ii)
RELATED LINKS
GitHub version: https://github.com/cncounter/translation/blob/master/tiemao_2015/20_JavaScript_Mastering_this/ Javascript_mastering_this.md
Original link: http://www.sitepoint.com/mastering-javascripts-this-keyword/
Author: Anchor Http://blog.csdn.net/renfufei
Date: September 22, 2015
Master JS in the "This" (ii)