Preface
The arrow function greatly simplifies this value selection rules.
Normal functions and arrow functions
A normal function refers to a function defined by a function:
var hello = function () { ("Hello, Fundebug!"); }
Arrow functions refer to functions defined with =>:
var hello = () => { ("Hello, Fundebug!"); }
JavaScript arrow functions and ordinary functions are not just the difference in writing, they also have some subtle differences, one of which is this.
The arrow function does not have its own this value, and the this used in the arrow function comes from the function scope chain.
This sentence is very simple, but it sounds a little confused, so I have to start from the beginning.
What exactly is this?
There are enough articles about this. Sometimes the more I draw it, the more I get, the more I get, I won’t make any more messes. I am only responsible for moving the MDN document: this. If you are interested, you can read it carefully. I will excerpt some of the most important words.
A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
JavaScript is a rather peculiar language. Its this is different from other languages, and its value depends on whether the code is strictly ("use strict").
What is the value of this?
The JavaScript context object in which the current code is executing.
This is the current context object when the code is executed.
Global context
In the global execution context (outside of any function), this refers to the global object whether in strict mode or not.
When the code is not executed in any function, it is executed in the global scope, the value of this is the global object, and for the browser, this is the window.
This rule is relatively easy to accept.
Function context
Inside a function, the value of this depends on how the function is called.
The value of this in the function depends on how the function is called. This rule is a bit abnormal and is also a place where bugs are easily found.
In addition, the value of this is also related to whether the function is strictly ("use strict"), which is very crazy...
If you are curious, it is useless to turn left to read the MDN document. I will say more, but only explain a simple situation.
As an object method
When a function is called as a method of an object, its this is set to the object the method is called on.
When a function's method is called as an object, its this value is the object.
var circle = { radius: 10, getRadius() { (); } }; (); // Print 10
self = this?
When we need to nest an inner function in an object method, this will cause us actual trouble. Everyone should have written such code:
// Use temporary variable selfvar circle = { radius: 10, outerDiameter() { var self = this; var innerDiameter = function() { (2 * ); }; innerDiameter(); } }; (); // Print20
The outerDiameter function is a method of the circle object, so its this value is the circle object.
Then it would be great for us to write directly, but unfortunately we can't write this, because the inner function innerDiameter does not inherit this value of the outer function outerDiameter. The value of the outerDiameter function is the circle object, which is equal to 10.
However, the value of innerDiameter function is not a circle object, so what exactly is it? It is the current context object when the innerDiameter function is executed. What is this context object? Actually, I was dizzy, so I might as well test it:
// This in innerDiameter function is windowvar circle = { radius: 10, outerDiameter() { var innerDiameter = function() { (this === window); }; innerDiameter(); } }; (); // Printtrue
This in the innerDiameter function is window. Why is it window? It doesn't care about it? It's not a circle object anyway.
Therefore, if we use this directly in the innerDiameter function, there will be a problem:
// Use normal functionsvar circle = { radius: 10, outerDiameter() { var innerDiameter = function() { (2 * ); }; innerDiameter(); } }; (); // PrintNaN
So, we have to use a temporary variable self to transfer this value of the outer function outerDiameter to the inner function innerDiameter.
.bind(this)
We can also use .bind(this) to avoid this changing problems:
// Use .bind(this)var circle = { radius: 10, outerDiameter() { var innerDiameter = function() { (2 * ); }; innerDiameter = (this); innerDiameter(); } }; (); // Print20
However, whether using the temporary variable self or using .bind(this), is not a very concise way.
In short, it is a bit strange to use this value for ordinary functions, especially when we use object-oriented programming, we often need to use this. Most of the time, we don’t use .bind(this), but use the temporary variables self or that to carry this value. Of course, it is not very pleasant to write, and we will write a bug if we accidentally.
As the MDN documentation says:
Until arrow functions, every new function defined its own this value based on how the function was called。This proved to be less than ideal with an object-oriented style of programming.
Arrow function
The rule for this to take the value of the arrow function is very simple, because this can be regarded as a normal variable in the arrow function.
An arrow function does not have its own this. The this value of the enclosing lexical scope is used; arrow functions follow the normal variable lookup rules.
The arrow function does not have its own this value. This used in the arrow function all comes from the function scope chain. Its value follows the same rules as ordinary variables and looks up layer by layer in the function scope chain.
With the arrow function, I just need to abide by the following rules and basically ignore this problem:
- For functions that need to be called using the() method, use normal function definitions, and do not use arrow functions. The value of this used in the object method has a definite meaning, which refers to the object itself.
- In other cases, all arrow functions are used.
// Use arrow functionvar circle = { radius: 10, outerDiameter() { var innerDiameter = () => { (2 * ); }; innerDiameter(); } }; (); // Print20
For the innerDiameter function innerDiameter, it does not have this value itself, and the use of this comes from the scope chain and comes from the scope of higher-level functions. The outer layer function outerDiameter of innerDiameter is an ordinary function, it has this value, and its this value is the circle object. Therefore, this used in the innerDiameter function comes from the outerDiameter function, whose value is the circle object.
in conclusion
JavaScript was designed by Brendan Eich after 10 days, so all kinds of inexplicable features are also one of the weird ones. Fortunately, the ECMAScript standard has developed rapidly and is very stable over the years. Using a new standard every year can make up for the innate shortcomings of JS.
The simplification of this value selection rules by arrow functions is actually to make less trouble for everyone. Who can remember so many rules and regulations of this value selection ordinary function? . .
In addition, MDN documents are definitely a treasure, you can read more.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.