By Dmitri Pavlutin

Click “like” and then look, wechat search [Big Move the world] pay attention to this person without dACHang background, but with a positive attitude upward. In this paper, making github.com/qq449245884… Has been included, the article has been categorized, also organized a lot of my documentation, and tutorial materials.

Everyone said there was no project on your resume, so I found one and gave it away【 Construction tutorial 】.

1. The Secret of this

Most of the time, JS this for our beginners is very easy to produce confusion. This is powerful, but it takes some work to understand.

In Java, PHP, or other standard languages, this represents an instance of the current object in a class method. In most cases, this should not be used outside of a method so that there is less confusion.

In order J, the situation is different: this represents the current execution context of the function. Function invocation in JS mainly has the following ways:

  • Function call: alert(‘Hello World! ‘)

  • Console. log(‘Hello World! ‘)

  • Constructor: new RegExp(‘\\d’)

  • Alert. Call (undefined, ‘Hello World! ‘)

Each call type defines the context in its own way, so it’s easy to get confused.

In addition, strict patterns can affect the execution context.

The key to understanding this is to be clear about function calls and how they affect context.

This article focuses on how functions are called and how this is affected, as well as illustrating common pitfalls of execution contexts.

Before we get started, a few terms:

Calling a function executes the code that creates the function body, or just calls the function. For example, the parseInt function call is parseInt (’15’).

  • Function call: Executes the code that forms the body of the function: for example, the parseInt function call is parseInt(’15’).

  • Call context: refers to the value of this in the function body. For example, map.set(‘key’, ‘value’) is called in the context of map.

  • The scope of a function: is the collection of variables, objects, and functions accessible in the function body.

2. Function calls

A function call is executed when an expression is followed by a function (, some comma-separated arguments and one), such as parseInt(’18’).

Function call expressions cannot be attribute calls, such as obj.myfunc (), which create a method call. [1,5].join(‘,’) is not a function call, but a method call.

A simple example of a function call:

function hello(name) { return 'Hello ' + name + '! '; } // call const message = hello('World'); console.log(message); // => 'Hello World! 'Copy the code

Hello (‘World’) is a function call: The hello expression is equivalent to a function followed by a pair of parentheses and a ‘World’ argument.

A more advanced example is IIFE(function expression called immediately)

const message = (function(name) { return 'Hello ' + name + '! '; })('World'); console.log(message) // => 'Hello World! 'Copy the code

IIFE is also a function call: the first pair of parentheses (function(name) {… }) is an expression that evaluates to a function object followed by a pair of parentheses whose argument is “World”.

2.1. This in function calls

This is a global object in a function call

The office object is determined by the execution environment. In browsers, this is the window object.

In function calls, the execution context is a global object.

Let’s look at the context in the following function:

function sum(a, b) { console.log(this === window); // => true this.myNumber = 20; // Add the 'myNumber' attribute to the global object return a + b; } // sum() is invoked as a function. The 'this' in sum() is a global object (window) sum(15, 16); // => 31 window.myNumber; / / = > 20Copy the code

When sum(15,16) is called, JS automatically sets this to the global object, which is window in the browser.

When this is used outside of any function scope (topmost scope: global execution context), this represents the Window object

console.log(this === window); // => true this.myString = 'Hello World! '; console.log(window.myString); // => 'Hello World! '<! -- In an html file --> <script type="text/javascript"> console.log(this === window); // => true </script>Copy the code

2.2 What does this look like in strict mode

This is undefined in strict mode function calls

Strict mode was introduced in ECMAScript 5.1 and provides better security and stronger error checking.

To enable strict mode, write use strict to the function header.

When enabled, strict mode affects the execution context, and this is undefined in regular function calls. In contrast to case 2.1 above, the execution context is no longer a global object.

Examples of strict mode function calls:

function multiply(a, b) { 'use strict'; // Enable strict mode console.log(this === undefined); // => true return a * b; } multiply(2, 5); / / = > 10Copy the code

When multiply(2,5) is called as a function, this is undefined.

Strict mode is valid not only in the current scope, but also in the inner scope (for all functions declared inside):

function execute() { 'use strict'; Function concat(str1, str2) {console.log(this === undefined); function concat(str1, str2) {console.log(this === undefined); // => true return str1 + str2; } // this in concat() is undefined ('Hello', 'World! '); // => "Hello World!" } execute();Copy the code

‘Use strict’ is inserted at the top of the body to enable strict mode in its scope. Because the function concat is declared in the scope of execution, it inherits the strict pattern.

A single JS file may contain strict and non-strict schemas. Therefore, for the same call type, you can have different contextual behavior in a single script:

Function nonStrictSum(a, b) {// nonStrictSum(a, b) {console.log(this === window); // => true return a + b; } function strictSum(a, b) { 'use strict'; // Enable strict mode console.log(this === undefined); // => true return a + b; } nonStrictSum(5, 6); // => 11 strictSum(8, 12); / / = > 20Copy the code

2.3 trap:thisIn the inner function

A common pitfall for function calls is to assume that this is the same in the inner function as it is in the outer function.

Correctly, the context of an inner function depends only on its call type, not on the context of an outer function.

To set this to the desired value, you can change the context of the internal function via.call() or.apply() or create a binding function using.bind().

The following example computes the sum of two numbers:

const numbers = { numberA: 5, numberB: 10, sum: function() { console.log(this === numbers); // => true function calculate() { console.log(this === numbers); // => false return this.numberA + this.numberB; } return calculate(); }}; numbers.sum(); // => NaNCopy the code

Sum () is a method call on an object, so the context in sum is a numbers object. The calculate function is defined in sum, and you might want this to also refer to the number object in calculate().

Calculate () is a function call (not a method call) that takes this as the global object Window (in non-strict mode). Even though the external function sum takes context as a number object, it has no effect in calculate.

The call to sum() results in NaN, not the expected result 5 + 10 = 15, all because calculate was not called correctly.

To solve this problem, the context in the Calculate function should be the same as in sum so that the numberA and numberB attributes can be accessed.

One solution is to manually change the Calculate context to the desired context by calling Calculator.Call (this).

const numbers = { numberA: 5, numberB: 10, sum: function() { console.log(this === numbers); // => true function calculate() { console.log(this === numbers); // => true return this.numberA + this.numberB; } // Use the.call() method to modify the context return calculate.call(this); }}; numbers.sum(); / / = > 15Copy the code

Call (this) performs the calculate function as usual, but call changes the context to the value specified as the first parameter.

Now this.numberA + this.numberB equals number. numberA + number. numberB. This function returns the expected result 5 + 10 = 15.

The other is to use the arrow function

const numbers = { numberA: 5, numberB: 10, sum: function() { console.log(this === numbers); // => true const calculate = () => { console.log(this === numbers); // => true return this.numberA + this.numberB; } return calculate(); }}; numbers.sum(); / / = > 15Copy the code

3. Method calls

Methods are functions stored in object properties. For example,

Const myObject = {// helloFunction is a method helloFunction: function() {return 'Hello World! '; }}; const message = myObject.helloFunction();Copy the code

HelloFunction is a method of myObject. To call this method, you can call myObject.helloFunction.

When an expression is executed as a property access, it is a method call, which is the equivalent of a function followed by (a comma-separated set of arguments and).

Using the previous example, myObject.helloFunction() is a method call to helloFunction on the object myObject. [1, 2]. Join (‘, ‘) or / \ s/test (‘ beautiful world ‘) is also considered a method call.

It is important to distinguish between function calls and method calls because they are different types. The main difference is that method calls require a property accessor form to call functions (obj.myfunc () or obj[‘myFunc’]()), while function calls do not (myFunc()).

['Hello', 'World'].join(', '); // call ({ten: function() {return 10; } }).ten(); // method calls const obj = {}; obj.myFunction = function() { return new Date().toString(); }; obj.myFunction(); // the method calls const otherFunction = obj.myfunction; otherFunction(); // Call parseFloat('16.60'); // call isNaN(0); // Function callCopy the code

Understanding the difference between a function call and a method call helps you correctly identify the context.

3.1 How does this look in method calls

In a method call, this is the object that owns the method

When a method on an object is called, this becomes the object itself.

Creates an object that has a method that increments numbers

const calc = { num: 0, increment: function() { console.log(this === calc); // => true this.num += 1; return this.num; }}; // method invocation. this is calc calc.increment(); // => 1 calc.increment(); / / = > 2Copy the code

Calling calc.increment() makes the increment function’s context a CALc object. So it is valid to increment the num attribute with this.num.

Let’s look at another example. A JS object inherits a method from a prototype, and when an inherited method is called on an object, the context of the call is still the object itself

const myDog = Object.create({
  sayName: function() {
     console.log(this === myDog); // => true
     return this.name;
  }
});
myDog.name = 'Milo';
// 方法调用 this 指向 myDog
myDog.sayName(); // => 'Milo'
Copy the code

Object.create() creates a new Object, myDog, and sets its prototype according to the first argument. MyDog inherits the sayName method.

When mydog.sayname () is executed, myDog is the context of the call.

In EC6 Class syntax, the method call context is also the instance itself

class Planet {
  constructor(name) {
    this.name = name;    
  }
  getName() {
    console.log(this === earth); // => true
    return this.name;
  }
}
var earth = new Planet('Earth');
// method invocation. the context is earth
earth.getName(); // => 'Earth'
 
Copy the code

3.2 Pitfall: Separating methods from their objects

Method can extract a single variable from the object const alone = myobj.myMethod. When the method is called alone, separated from the original object alone(), you might think that the current this is the myObject that defines the method.

The function call occurs if the method is called without an object, and this refers to the global object window, which is undefined in strict mode.

The following example defines the Animal constructor and creates an instance of it :myCat. Then setTimout() prints the myCat object information after 1 second

function Animal(type, legs) {
  this.type = type;
  this.legs = legs;  
  this.logInfo = function() {
    console.log(this === myCat); // => false
    console.log('The ' + this.type + ' has ' + this.legs + ' legs');
  }
}
const myCat = new Animal('Cat', 4);
// The undefined has undefined legs 
setTimeout(myCat.logInfo, 1000); 
Copy the code

You might think that when setTimout calls mycat.logInfo (), it should print information about the myCat object.

Unfortunately, methods are separated from objects when passed as arguments, and setTimout(mycat.loginfo) is equivalent:

setTimout(myCat.logInfo); // Const extractedLogInfo = mycat.loginfo; setTimout(extractedLogInfo);Copy the code

When the detached logInfo is called as a function, this is the global window, so the object information is not printed correctly.

The function can fix the problem this points to by binding to the object using the.bind() method.

function Animal(type, legs) {
  this.type = type;
  this.legs = legs;  
  this.logInfo = function() {
    console.log(this === myCat); // => true
    console.log('The ' + this.type + ' has ' + this.legs + ' legs');
  };
}
const myCat = new Animal('Cat', 4);
// logs "The Cat has 4 legs"
setTimeout(myCat.logInfo.bind(myCat), 1000);
Copy the code

Mycat.loginfo.bind (myCat) returns a new function that performs exactly the same as logInfo, but this points to myCat, even in function calls.

Another solution is to define the logInfo() method as an arrow function:

function Animal(type, legs) {
  this.type = type;
  this.legs = legs;  
  this.logInfo = () => {
    console.log(this === myCat); // => true
    console.log('The ' + this.type + ' has ' + this.legs + ' legs');
  };
}
const myCat = new Animal('Cat', 4);
// logs "The Cat has 4 legs"
setTimeout(myCat.logInfo, 1000);
Copy the code

Constructor calls

Called when the new keyword is followed by the function object,(, a set of comma-delimited arguments, and), a constructor call such as new RegExp(‘\\d’) is performed.

Declare a Country function and call it as a constructor:

function Country(name, traveled) { this.name = name ? name : 'United Kingdom'; this.traveled = Boolean(traveled); } Country.prototype.travel = function() { this.traveled = true; }; // Constructor calls const France = new Country('France', false); // constructor calls const unitedKingdom = new Country; france.travel(); // Travel to FranceCopy the code

New Country(‘France’, false) is a constructor call to Country. The result is a new object with a name attribute of ‘France’. If the constructor is called without arguments, the parentheses can be omitted: new Country.

Starting with ES6, JS allows constructors to be defined using the class keyword

class City {
  constructor(name, traveled) {
    this.name = name;
    this.traveled = false;
  }
  travel() {
    this.traveled = true;
  }
}
// Constructor invocation
const paris = new City('Paris', false);
paris.travel();
Copy the code

New City(‘Paris’) is the constructor call. Initialization of this object is handled by a special method in this class called constructor. Where this refers to the newly created object.

The constructor creates a new empty object that inherits properties from the constructor’s prototype. The constructor is used to initialize the object. As you probably already know, in this type of call, the context points to the newly created instance.

When a property calls myObject.myFunction with a new keyword in front of it, JS executes the constructor call instead of the original method call.

For example, new MyObject.myFunction () : this is equivalent to extracting the method from the property access extractedFunction = myObject.myFunction and then creating a new object using it as a constructor: New extractedFunction ().

4.1. This in the constructor

In the constructor call this points to the newly created object

The context of the constructor call is the newly created object. It uses constructor parameters to initialize new objects, set initial values for properties, add event handlers, and so on.

Take a look at the context in the following example

function Foo () {
  console.log(this instanceof Foo); // => true
  this.property = 'Default Value';
}
// Constructor invocation
const fooInstance = new Foo();
fooInstance.property; // => 'Default Value'
Copy the code

New Foo() is making a constructor call where the context is fooInstance. Initialize the object inside Foo: this.property is assigned the default value.

The same happens with class syntax (as of ES6), the only difference being that initialization is done in the constructor method:

class Bar {
  constructor() {
    console.log(this instanceof Bar); // => true
    this.property = 'Default Value';
  }
}
// Constructor invocation
const barInstance = new Bar();
barInstance.property; // => 'Default Value'
Copy the code

4.2. Trap: Forgetting to use new

Some JS functions create new objects not only when called as constructors, but also when called as functions, such as RegExp:

var reg1 = new RegExp('\\w+');
var reg2 = RegExp('\\w+');

reg1 instanceof RegExp;      // => true
reg2 instanceof RegExp;      // => true
reg1.source === reg2.source; // => true
Copy the code

When new RegExp(‘\\w+’) and RegExp(‘\\w+’) are executed, JS creates the equivalent regular expression object.

There is a potential problem with using function calls to create objects (excluding the factory pattern) because some constructors may ignore the logic to initialize objects in the absence of the new keyword.

The following example illustrates the problem:

function Vehicle(type, wheelsCount) { this.type = type; this.wheelsCount = wheelsCount; return this; } // Forget to use new const car = Vehicle(' car ', 4); car.type; // => 'Car' car.wheelsCount // => 4 car === window // => trueCopy the code

Vehicle is a function that sets the Type and wheelsCount properties on the context object.

When Vehicle(‘Car’, 4) is executed, an object called Car is returned with the right attributes :Car.type is Car and car.wheelsCount is 4, which you might think would be good for creating and initializing new objects.

However, in function calls, this is the Window object, so Vehicle (‘Car’, 4) sets properties on the window object. Clearly this is an error, and it does not create a new object.

When you want to call the constructor, make sure you use the new operator:

function Vehicle(type, wheelsCount) { if (! (this instanceof Vehicle)) { throw Error('Error: Incorrect invocation'); } this.type = type; this.wheelsCount = wheelsCount; return this; } // Constructor invocation const car = new Vehicle('Car', 4); car.type // => 'Car' car.wheelsCount // => 4 car instanceof Vehicle // => true // Function invocation. Throws an error. const brokenCar = Vehicle('Broken Car', 3);Copy the code

New Vehicle(‘Car’, 4) works fine: a new object is created and initialized because the constructor call uses the new keyword.

A validation of this Instanceof Vehicle has been added to the constructor to ensure that the execution context is the correct object type. If this is not Vehicle, an error is reported. Thus, if Vehicle(‘Broken Car’, 3)(no new) is executed, we get an Error: Incorrect Invocation.

5. Implicit invocation

When a function is called using the myfun.call () or myfun.apply () methods, implicit calls are performed.

Functions in JS are first class objects, which means functions are objects, and objects are of type Function. From the list of methods on function objects,.call() and.apply() are used to call functions with configurable contexts.

  • Call (thisArg[, arg1[, arg2[,…]]]) takes thisArg as the first argument in the context of the call, arg1, arg2… These are passed as arguments to the function being called.

  • Apply (thisArg, [args]) takes thisArg, the first argument it accepts, as the call context, and accepts another array-like object [arg1, arg2,…]. Passed as an argument to the called function.

The following is an example of implicit invocation

function increment(number) { return ++number; } increment.call(undefined, 10); // => 11 increment.apply(undefined, [10]); / / = > 11Copy the code

Increment.call () and increment.apply() both call this incrementing function with argument 10.

The difference is. Call () takes a set of arguments, e.g. Myfunction.call (thisValue, ‘value1’, ‘value2’). The set of arguments accepted by.apply() must be an array-like object, for example myfunction.apply (thisValue, [‘value1’, ‘value2’]).

5.1. Implicitly calling this in

In an implicit call to.call() or.apply(), this is the first argument

Obviously, in implicit calls, this is passed as the first argument to.call() or.apply().

var rabbit = { name: 'White Rabbit' };
function concatName(string) {
  console.log(this === rabbit); // => true
  return string + this.name;
}
concatName.call(rabbit, 'Hello ');  // => 'Hello White Rabbit'
concatName.apply(rabbit, ['Bye ']); // => 'Bye White Rabbit'
Copy the code

Implicit invocation is useful when a function should be executed in a particular context. For example, to solve the context problem of method calls where this is always window or undefined in strict mode. Implicit invocation can be used to simulate calling a method on an object.

function Runner(name) {
  console.log(this instanceof Rabbit); // => true
  this.name = name;  
}
function Rabbit(name, countLegs) {
  console.log(this instanceof Rabbit); // => true
  Runner.call(this, name);
  this.countLegs = countLegs;
}
const myRabbit = new Rabbit('White Rabbit', 4);
myRabbit; // { name: 'White Rabbit', countLegs: 4 }
Copy the code

The Runner. Call (this, name) in Rabbit implicitly calls the superclass function to initialize the object.

6. Bind functions

A binding function is a function that connects to an object. It is usually created from the original function using the.bind() method. The original and binding functions share the same code and scope, but are executed in different contexts.

The method myfunc.bind (thisArg[, arg1[, arg2[,…]]]) accepts the first argument thisArg as the context in which the binding function is executed, and it accepts an optional set of arguments arg1, arg2… As arguments to the function being called. It returns a new function bound to thisArg.

function multiply(number) { 'use strict'; return this * number; } const double = multiply.bind(2); double(3); // => 6 double(10); / / = > 20Copy the code

Bind (2) returns a new function object, double, which binds the number 2. Multiply and double have the same code and scope.

In contrast to the.apply() and.call() methods, which do not call the function immediately, the.bind() method simply returns a new function that will be called later, except that this has been set up in advance.

6.1. Bind this in functions

This is the first argument to.bind() when the binding function is called.

The job of.bind() is to create a new function that, when called, passes context as the first argument to.bind(). It is a powerful technique that allows us to create a function that defines this.

How to set this in the binding function

const numbers = { array: [3, 5, 10], getNumbers: function() { return this.array; }}; const boundGetNumbers = numbers.getNumbers.bind(numbers); boundGetNumbers(); // => [3, 5, 10] // Extract method from object const simpleGetNumbers = numbers.getNumbers; simpleGetNumbers(); // => undefined (error in strict mode)Copy the code

Numbers. GetNumbers. Bind (numbers) returns the boundGetNumbers function bound to numbers. BoundGetNumbers () calls this as a number object and returns the correct array object.

The function numbers. GetNumbers can be extracted into the variable simpleGetNumbers without binding. In subsequent function calls, this of simpleGetNumbers() is window(undefined in strict mode), not number. In this case, simpleGetNumbers() will not return the array correctly.

6.2 Tight context binding

.bind() creates a permanent context link and always holds it. A binding function cannot change its context with.call() or.apply(), or even bind it again.

Only constructor calls to binding functions can change the context of the binding, but this is not recommended (constructor calls must use regular unbound functions).

The following example creates a binding function and then tries to change its predefined context

function getThis() { 'use strict'; return this; } const one = getThis.bind(1); // The binding function calls one(); / / / / use a = > 1. The apply () and call () the binding function. One call (2); // => 1 one.apply(2); // bind one.bind(2)(); // call the binding function new one() as a constructor; // => ObjectCopy the code

Only new One () changes the context of the binding function; otherwise this is always equal to 1.

7. Arrow function

Arrow functions are used to declare functions in shorter form and bind context lexically. It can be used like this

const hello = (name) => { return 'Hello ' + name; }; hello('World'); // => 'Hello World' // Keep only even numbers [1, 2, 5, 6].filter(item => item % 2 === 0); / / = > [2, 6]Copy the code

Arrow functions have simple syntax and no verbose function keyword. You can even omit the return keyword when the arrow function has only one statement.

The arrow function is anonymous, which means that the name attribute is an empty string “”. This way it has no lexical function name (which is useful for recursive, detached event handlers)

Also, it does not provide arguments objects, as opposed to regular functions. However, this is fixed in ES6 with rest Parameters:

const sumArguments = (... args) => { console.log(typeof arguments); // => 'undefined' return args.reduce((result, item) => result + item); }; sumArguments.name // => '' sumArguments(5, 5, 6); / / = > 16Copy the code

7.1. This in the arrow function

This defines the enclosing context of the arrow function

Instead of creating its own execution context, the arrow function gets this from the external function that defines it. In other words, the arrow function binds this lexically.

The following example illustrates the context transparency:

class Point { constructor(x, y) { this.x = x; this.y = y; } log() { console.log(this === myPoint); // => true setTimeout(()=> { console.log(this === myPoint); // => true console.log(this.x + ':' + this.y); // => '95:165'}, 1000); } } const myPoint = new Point(95, 165); myPoint.log();Copy the code

SetTimeout calls the arrow function using the same context (myPoint object) as the log() method. As you can see, the arrow function inherits context from the function that defines it.

If you try to use a normal function in this example, it creates its own context (window or undefined in strict mode). Therefore, to make the same code use function expressions correctly, you need to manually bind the context :setTimeout(function(){… }. The bind (this)). This is verbose, and using arrow functions is a cleaner, shorter solution.

If the arrow function is defined in the top-level scope (outside of any function), the context is always the global object (window in the browser) :

onst getContext = () => {
   console.log(this === window); // => true
   return this;
};
console.log(getContext() === window); // => true
Copy the code

The arrow function is bound to the lexical context once and for all. This cannot be changed even if the context is changed:

const numbers = [1, 2];
(function() {  
  const get = () => {
    console.log(this === numbers); // => true
    return this;
  };
  console.log(this === numbers); // => true
  get(); // => [1, 2]
  // Use arrow function with .apply() and .call()
  get.call([0]);  // => [1, 2]
  get.apply([0]); // => [1, 2]
  // Bind
  get.bind([0])(); // => [1, 2]
}).call(numbers);
Copy the code

No matter how you call the arrow function GET, it always preserves the lexical context numbers. Implicit calls from other contexts (via get.call([0]) or get.apply([0])) or rebinding (via.bind()) will not work.

Arrow functions cannot be used as constructors. Calling it as a constructor (new get()) throws an error: TypeError: Get is not a constructor.

7.2. Trap: Define methods with arrow functions

You might want to use arrow functions to declare methods on an object. Arrow function definitions are much shorter than function expressions :(param) => {… } instead of function(param) {.. }.

For example, the format() method is defined on the Period class using the arrow function:

function Period (hours, minutes) {  
  this.hours = hours;
  this.minutes = minutes;
}
Period.prototype.format = () => {
  console.log(this === window); // => true
  return this.hours + ' hours and ' + this.minutes + ' minutes';
};
const walkPeriod = new Period(2, 30);  
walkPeriod.format(); // => 'undefined hours and undefined minutes'
Copy the code

Since format is an arrow function and is defined in the global context (the top-level scope), this refers to the Window object.

Even if format is called as a method on an object such as walkperiod.format (), window is still the context of the call. This happens because arrow functions have a static context and do not change with the way they are called.

This method returns ‘undefined hours and undefined minutes’, which is not what we want.

Function expressions solve this problem, because a regular function can really change its context based on the actual call:

function Period (hours, minutes) {  
  this.hours = hours;
  this.minutes = minutes;
}
Period.prototype.format = function() {
  console.log(this === walkPeriod); // => true
  return this.hours + ' hours and ' + this.minutes + ' minutes';
};
const walkPeriod = new Period(2, 30);  
walkPeriod.format(); // => '2 hours and 30 minutes'
Copy the code

Walkperiod.format () is a method call on an object whose context is the walkPeriod object. This. hours equals 2 and this.minutes equals 30, so this method returns the correct result: ‘2 hours and 30 minutes’.

The original:Dmitripavlutin.com/gentle-expl…

The bugs that may exist after code deployment cannot be known in real time. In order to solve these bugs, I spent a lot of time on log debugging. Incidentally, I recommend a good BUG monitoring tool for youFundebug.

conclusion

For function calls that affect this the most, from now on don’t ask yourself:

Where does this come from?

It’s about looking at

How is the function called?

For the arrow function, you have to think about it

Where the arrow function is defined, what is this?

These are the right ideas for dealing with this, and they can save you headaches.

communication

This article is updated every week, you can search wechat “big move the world” for the first time to read and urge more (one or two earlier than the blog hey), this article GitHub github.com/qq449245884… It has been included and sorted out a lot of my documents. Welcome Star and perfect. You can refer to the examination points for review in the interview.