The direction of this in JavaScript (Introduction)

Time:2021-11-25

Make a classification before writing. There are six situations:

  1. This in function//Point to the caller itself
  2. This in arrow function () = > {}//This is the closest function runtime at definition time
  3. This in call, bind, apply, etc//Point to the redirected this
  4. This of arrow function in call, bind, apply, etc//This is the closest function runtime at definition time
  5. This in funciton callback function//Void call, pointing to the global
  6. This in the arrow function callback function//This is the closest function runtime at definition time

From simple to deep analysis:

1. This in funPoint to the caller itself

The most basic this pointing problem is that which object call points to this object.
For example, in DOM operations:
Document. Getelementbyid ('btn '). Onclick = function() {console. Log (this);} // when BTN is clicked, this points to document. Getelementbyid ('btn')
Here onclick is a function. When clicked = > document. Getelementbyid (‘btn ‘) calls the onclick function, so it points to document. Getelementbyid (‘btn’);
For example, in object:

const man = { 
         age: 18, 
         getAge: function(){console.log(this.age)},
      }; 
window.age = 0;
man.getAge(); // 18
const getAge = man.getAge;
getAge(); // 0

Getage is just a function. When called by man, it points to man, and when called globally, it points to window (in strict mode, it points to undefined, which will be discussed in the next article on memory)

2. This in arrow function () = > {}//This is the closest function runtime at definition time

It sounds a little tongue twister, but the reason is simple,
The arrow function itself is designed for anonymous functions,
Without its own this and arguments,Both are attached to the function closest to the definition
andThis of function depends on the calling object when it runs, so merging is
Closest function when defined + this when running
Three examples:
1.const a = {cb: function(){setTimeout(() => console.log(this))}};
const fn = () => console.log(this); // Arrow function, global
2. Const B = {CB: function() {setTimeout (FN)}} // introduced into b.cb through variable name
3. Const C = {CB: function (params_fn) {setTimeout (params_fn)}} // in the experiment, FN is introduced into c.cb by passing parameters

Then run one by one

a. Cb() // this points to a because the arrow defines the closest function - > CB. This is attached to CB. CB is called by a when it runs
b. Cb() // this points to the window. Because the arrow definition is a void definition and points to the global, it points to the window at runtime
c. CB (FN) // this points to window for the same reason as B

The above example is not enough to prove that this is the closest function to the attachment. Add another one
const cb = a.cb;
cb();// This points to window
It can be seen that this of the arrow function is directly attached to the closest function at the time of definition. The direction of this depends onOperating environment of auxiliary function

3 + 4. bind ,call ,apply

These three are simple, because everyone who has used them knows that they forcibly change the direction of this,For example, bind (‘hard gas’) is equivalent to a decorator, directly this = ‘hard gas’However, because the arrow function does not have this and arguments, it does not take effect on the arrow function, and the direction of the arrow function is not affected.

5 + 6. This point in callback function

In the callback function, regardless of function or () = > {}, the operation actually belongs to virtual operation. What is called virtual operation isNo call objectAnd when there is no calling object,
This of function generally points to the global (undefined in strict mode),
The arrow function still depends on the subsidiary this to determine the direction of this.
Callback functions are generally defined within a function,The arrow function can easily determine the direction of this without changing the direction of this inside the callback functionTherefore, this is also the reason why callback functions use arrow functions more.

Expand: anti shake function

The knowledge point of the anti shake function itself is closure, but a timer in it uses the technique of this pointing

Write a regular anti shake

function dobounce(fn, time = 1000) {
    let timeout = null; //  Create variable
    return function() {
        if(timeout) clearTimeout(timeout); // If there is already a timer, clear the timer
        timeout = setTimeout(() => fn.apply(this, arguments), time); //  Recreate timer
    }
}

The arrow function in setTimeout () here directly inherits the this and arguments of the closure return value function, and then calls this anti shake.
a = {name: 4, test: dobounce(function(a, b) {console.log(this.name + a + b)})};
a.test(5, 6) // 15
However, don’t use the arrow function for the FN passed in the anti shake. The reason is that the arrow function points to this.

Summary:

Because the arrow function does not have its own this, it will not be changed by various external factors,Only the function closest to the definition is attached
And function Generally, this depends on the calling objectHowever, this point can be changed by bind, call, apply, etc. if it is a null operation (in the callback function, it points to the global)