<> Thoroughly understand JavaScript in this point

In almost all object-oriented programming languages this Keywords for , as Java,C++,Swift Medium this,Python,Object-C Medium self, however Javascript Medium this Not quite like them , In object-oriented programming languages this Usually occurs in class methods , Represents the current calling object , and Javascript Medium this More flexible and complex .JavaScript in this Is a very special keyword , Automatically defined in the scope of all functions ,MDN Mentioned in JavaScript of this Is a property of the current execution context , In non strict mode , Always point to an object , Can be any value in strict mode . that ,JavaScript Why is it used in this? its this What kind of mechanism is used for binding ?

<> one , Why use this

Let's look at the following code , without this, We want to get the name of this object through the reference to the variable Tom.name
To achieve , This method of explicit reference is obviously inappropriate , If the variable name needs to be modified one day , Then all references in the object must also be modified .
var Tom = { name: 'Tom', speaking: function () { console.log(`${Tom.name} say
boh`) }, language: function () { console.log(`${Tom.name}'s mother tongue is
Chinese`) }, hobby: function () { console.log(`${Tom.name} love eating,
sleeping and playing peas`) }, }
When we have this in the future , Can be referenced in a more elegant way , Make the code more concise , More reusability . actually ,this It brings us more convenience than that .
var Tom = { name: 'Tom', speaking: function () { console.log(`${this.name} say
boh`) }, language: function () { console.log(`${this.name}'s mother tongue is
Chinese`) }, hobby: function () { console.log(`${this.name} love eating,
sleeping and playing peas`) }, }
<> two ,this What does it point to

<>2.1 Two misunderstandings

<>2.1.1 Misunderstanding one : Point to itself

Take the following counter as an example : The output is 0 instead of 10, Obviously in this example this Does not point to itself
function counter() { this.count++ } counter.count = 0 for (let i = 0; i < 10; i
++) { counter(i) } console.log(counter.count) // 0
<>2.1.2 Misunderstanding II : Point to its scope

Take the following function nested call as an example : The output is undefined, And no value on output scope
function func1() { var a = 1 func2() } function func2() { var a = 2 console.log
(this.a) } func1() // undefined
<>2.2 this Binding mechanism

in fact ,this Is bound when the function is running , It and this It doesn't matter where you define , But with this The calling position of is related to the calling method , He has four binding methods , Namely
Default binding , Explicit binding , Implicit binding ,new binding .

<>2.2.1 Default binding

The default binding rule will be used when the function is called independently , It can be considered as the final decision after it does not comply with other binding rules , In non strict mode , The default binding will this Bind to global variables window
upper , In strict mode ,this Will be bound to undefined.( notes : Not considered here nodejs)
var a = 1 function func1() { console.log(this.a) } function func2() { 'use
strict' console.log(this.a) } console.log(this) func1() // 1 func2() //
<>2.2.2 Implicit binding

If the function is called through an object , that this Will point to the object that calls the function .
let obj = { showThis: function () { console.log(this===obj) } } obj.showThis()
// true
What if a chain call is made ? Look at the following example , obvious , In this chained call, only the last layer of calls works .
let obj = { showThis: function () { console.log(this===obj) }, } let obj2 = {
obj: obj, } obj2.obj.showThis() //true
Of course not through this . The calling method will be bound to . On previous objects , It is worth noting that , Sometimes there is an implicit loss , In the following example, the output is window instead of obj
, Because the implicit binding was lost when passing , The passed in can be regarded as the function itself , and obj It doesn't matter .
function func1() { console.log(this) } var obj = { func: func1, } var func2 =
obj.func func2() // window
<>2.2.3 Explicit binding

Implicit binding has many limitations , There must be a property that points to a function inside the object
, And indirectly reference functions through this attribute , So that this Bind to object , So if we don't want to include such a function reference inside the object , And I want to this What about binding to this object for function calls ? It can be used at this time **
call,apply perhaps bind method ** Force binding , It should be noted that , Here the binding and object [[Prototype]] relevant , Therefore, arrow functions cannot be explicitly bound .
function func() { console.log(this); } func.call(window); // window func.apply(
{}); // {} func.bind(1)(); // Number {1} Here is a numeric object 1
Used here bind Binding is also called hard binding , It can effectively solve the problem of implicit binding loss , It is already in JavaScript Internal implementation , Its internal implementation principle is very simple :
function bind(func, obj) { return function() { return func.apply(obj, arguments
); } }
In many places , Will give one more parameter for explicit binding , as setTimeout,forEach etc. , Its internal is also through call or apply
Implemented , Can effectively help us reduce the code

<>2.2.4 new binding

use new Keyword to make a function call is often called a constructor call , Actually in JavaScript Except for the arrow function, you can use this method to call , The following actions are performed automatically when called :

* Create a new object
* This new object will be executed Prototype connect
* This new object will be bound to the function call this upper
* If the function does not return another object , The expression will automatically return the new object function Person(name) { console.log(this); this.
name= name; } var tom = new Person('Tom'); // Person {} console.log(tom); //
Person {name: 'Tom'}
<> three , Binding priority

If a function call location , The method uses many of the above four rules. Which priority will be used ?

<>3.1 What is the priority

The answer is :new binding > Explicit binding > Implicit binding > Default binding

<>3.2 Explicit binding > Implicit binding

Output is obj2 Description explicit binding is in effect , Implicit binding does not take effect
function foo() { console.log(this); } var obj1 = { foo: foo } var obj2 = { foo:
foo} obj1.foo.call(obj2); // function foo() { console.log(this) } var obj1 = {
name: 'obj1', foo: foo, } var obj2 = { name: 'obj2', foo: foo, } obj1.foo.call(
obj2) // {name: 'obj2', foo: ƒ}, explain Explicit binding > Implicit binding
<>3.3 new binding > Explicit binding

new And call,apply Is used simultaneously in JavaScript Not allowed during , Error will be reported TypeError
, But you can bind Hard bound functions are used at the same time , The output here is foo, explain new Binding is in effect
function foo() { console.log(this) } var obj = { name: "obj" } var bar = foo.
bind(obj) var baz = new bar() // foo {}, explain new binding > Explicit binding
<> four , There will always be some accidents

<>4.1 Ignored explicit binding

If in display binding , Pass in a null perhaps undefined, Then the display binding will be ignored , Use default binding .
function foo() { console.log(this) } foo.call(null) // window
So if you just want to this What should we do to bind to any object ? Explicitly bind an empty object , Note that the object is empty, not null, Its creation method is :

<>4.2 Indirect reference

The default binding rules are also used when using indirect references to functions , What is an indirect reference can be seen from a simple example :
var num1 = 2 var num2 = 3 var res = (num2 = num1) console.log(num1, num2, res)
// 2 2 2
For functions , The same pattern , Call it an indirect reference
function foo() { console.log(this) } var obj1 = { name: "obj1", foo: foo }; var
obj2= { name: "obj2" } obj1.foo() (obj2.foo = obj1.foo)(); // window
<> five , summary

that , How do we ultimately judge this Point ? Usually, the following steps can be taken :

* Judge whether it is an arrow function , Arrow function this Always point to its nearest execution context
* Judge whether it is new binding ,new Highest binding priority ,this point new Objects coming out
* Determine whether it is an explicit binding ,this Point to bound object
* Determine whether it is implicit binding ,this Usually point to . The previous object that calls the function
* Finally, consider whether it is the default binding , according to JavaScript The execution mode is judged as window Or this undefined
Implicit loss should be considered in special cases , Explicit binding null, Indirect reference

Reference books :《 You don't know JavaScript Roll up 》