JavaScript in Plain English series:
- Lesson 1: What is this in the arrow function?
- Lesson 2: What does it mean that a function is a first-class citizen?
- Lesson 3: What is garbage Collection?
- Lesson 4: How does the V8 engine work?
- Lesson 5: How Chrome works
Ordinary and arrow functions
Common functionRefers to a function defined with function:
var hello = function () {
console.log("Hello, Fundebug!");
}
Copy the code
Arrow functionRefers to a function defined with => :
var hello = (a)= > {
console.log("Hello, Fundebug!");
}
Copy the code
JavaScript arrow functions differ from normal functions in more than just the way they are written, there are some subtle differences, one of which is this.
Arrow functions do not have their own this value; the this used in arrow functions comes from the function scope chain.
This sentence is very simple, but sounds a little puzzling, have to start from the beginning.
What is this?
There are enough articles about this, sometimes the more the more dark, I will not add to the mess, I am only responsible for moving the MDN document: this, interested can read carefully, I will extract 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 strange language; its this is different from other languages, and its value depends on whether the code is “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 executes.
Global context
In the global execution context (outside of any function), this refers to the global object whether in strict mode or not.
The code is not executed in any function, but in the global scope, where the value of this is the global object, and to 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 rule that the value of this in a function depends on how the function is called is a bit perverted and buggy.
In addition, the value of this depends on whether the function is “use strict”, which is pretty crazy…
If you’re curious, go out and turn left and look at the MDN documentation, and I’m not going to say much, but I’m just going to illustrate a simple case.
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 is called as a method of an object, its this value is that object.
var circle = {
radius: 10,
getRadius() {
console.log(this.radius); }}; circle.getRadius();/ / print 10
Copy the code
The self = this?
This can cause real trouble when we need to nest an inner function in an object method. You’ve probably written code like this:
// Use the temporary variable self
var circle = {
radius: 10,
outerDiameter() {
var self = this;
var innerDiameter = function() {
console.log(2* self.radius); }; innerDiameter(); }}; circle.outerDiameter();/ / print 20
Copy the code
The outerDiameter function is a circle method, so its this value is circle.
Radius = this.radius = this.radius = this.radius = this.radius = this.radius = this.radius = this.radius = this.radius = this.radius The outerDiameter function’s this is the circle object, this.radius equals 10.
But what is innerDiameter? This is not a circle. This is the context object in which the innerDiameter function is executed. What is this context object? I’m actually dizzy too, so I might as well test this out:
// This in the innerDiameter function is the window
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = function() {
console.log(this= = =window); }; innerDiameter(); }}; circle.outerDiameter();/ / print true
Copy the code
This in the innerDiameter function is a window, which is not a circle object.
Therefore, if we use this directly in the innerDiameter function, we have a problem:
// Use normal functions
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = function() {
console.log(2 * this.radius); }; innerDiameter(); }}; circle.outerDiameter();/ / print NaN
Copy the code
We then have to use a temporary variable, self, to carry the this value of outerDiameter into the innerDiameter function.
.bind(this)
We can also use.bind(this) to get around the problem of this changing:
/ / using the bind (this)
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = function() {
console.log(2 * this.radius);
};
innerDiameter = innerDiameter.bind(this); innerDiameter(); }}; circle.outerDiameter();/ / print 20
Copy the code
However, using either the temporary variable self or.bind(this) is not a very neat way to do this.
In general, the value of this in ordinary functions is a little bit strange, especially when we’re programming in an object-oriented way, and we’re going to use this a lot of the time, and most of the time we’re not going to use.bind(this), we’re going to use the temporary variable self or that to carry the value of this, and it’s not very fun to write, And you can write bugs if you’re not careful.
As the MDN document states:
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 in the arrow function is very simple, because in the arrow function, this can be treated as a normal variable.
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.
Arrow functions do not have their own this value. Arrow functions use this values from the function scope chain, which follow the same rules as ordinary variables.
With the arrow function, I can basically ignore this as long as I follow the following rules:
- For use
object.method()
Use the normal function definition, not the arrow function. The this value used in object methods has a definite meaning and refers to the object itself. - In other cases, use all arrow functions.
// Use the arrow function
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = (a)= > {
console.log(2 * this.radius); }; innerDiameter(); }}; circle.outerDiameter();/ / print 20
Copy the code
The innerDiameter function does not have a this value of its own. It uses this from the scope chain, from the scope of the higher-level function. OuterDiameter is a normal function. The outerDiameter function has this, which is the circle object. Therefore, the this used in the innerDiameter function comes from the outerDiameter function and has a value of the circle object.
conclusion
JavaScript was designed by Brendan Eich in 10 days, so this is one of those weird features. Fortunately, the ECMAScript standard has been developing rapidly and steadily in recent years, and a new standard has been developed every year to make up for the inherent shortcomings of JS.
The arrow function simplifies the this value rule, in fact, is to reduce the confusion for everyone, who can remember the ordinary function this value so many rules ah…
In addition, the MDN documentation is definitely a treasure trove that you can read more about.
About JS, I plan to start a series of blogs, what else are you not clear about? Leave a comment so I can study it and share it with you. Also welcome to add my personal wechat (KiwenLau), I am the technical director of Fundebug, a programmer who loves and hates JS.
reference
- ES6 In Depth: Arrow functions
- MDN document – this
About Fundebug
Fundebug focuses on real-time BUG monitoring for JavaScript, wechat applets, wechat games, Alipay applets, React Native, Node.js and Java online applications. Since its official launch on November 11, 2016, Fundebug has handled over 1 billion error events in total, and paid customers include Sunshine Insurance, Walnut Programming, Lychee FM, Zhangmen 1-to-1, Weimai, Qingtuanshe and many other brand enterprises. Welcome to try it for free!
Copyright statement
Reprint please indicate the author Fundebug and this article addresses: blog.fundebug.com/2019/06/18/…