Make a classification before writing. There are six situations:
- This in function//
Point to the caller itself
- This in arrow function () = > {}//
This is the closest function runtime at definition time
- This in call, bind, apply, etc//
Point to the redirected this
- This of arrow function in call, bind, apply, etc//
This is the closest function runtime at definition time
- This in funciton callback function//
Void call, pointing to the global
- 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 isClosest 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 oneconst 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)