preface

To be honest, it would take more than three days and nights to explain this in detail, and there are many detailed explanations of this in a variety of books. It can be said that this is ubiquitous in JavaScript and has a wide range of applications. Let’s take a good look at this

“This” this

define

We all know that js execution generates a global context, and function execution also generates a function execution context. When a function is called, an execution context is created. The execution context contains where the function was called (call stack), how the function was called, and the argument passed in. This is an attribute used to record the execution context information.

This “belong”

So who does this belong to?

In a simple sentence, the most direct context of the current method is the proximity principle. That is, where the execution of the function is in the call stack, and where the function’s this points to. (Not considering strict mode)

Global context

console.log(this= = =window) //true

var a = 4

console.log(this.a) / / 4
Copy the code

In browsers, in strict mode or not, our this refers to our window in the global context (because it is called in the global context), and since there is no concept of window in the Node environment, the print result will be undefined

Function context

function foo(){

   //use strict Specifies the strict mode
   
    console.log(this.a) / / 2
    
}

var a = 2

foo()
Copy the code

Foo () is called globally, so this in foo also refers to window, so this.a equals window.a, and the output is 2.

In strict mode, this is bound to undefined regardless of the scope of the call

Let’s take a look at one more piece of code to understand what this refers to

var a = 1

function baz(){

    This refers to the global window of the call stack
    
    let a = 2

    console.log('this.a');

    bar()

}

function bar(){

    // The call position is baz of the call stack -> bar this points to baz

      let a = 3

    console.log('this.a');

    foo()

}

function foo(){

    Baz -> bar -> foo this points to bar

      let a = 4

    console.log('this.a');

}

baz() / / baz calls
Copy the code

The code analysis

Let’s look at the code above, look at three printouts, and think about what this.a prints out.

In the global context, we define baz (), bar (), and foo (). Baz () is called in the global context, so its this pointer points to the window. Bar () is called in baz (), and this refers to the execution context of the baz function; Foo (), in the same way, has its internal this pointing to the execution context of bar (), so the layers of this are nested so that they all end up pointing to window, which means this.a equals window.a when printed. This actually refers to the function context in which the method was called), so it prints all 1.

Of course, there are several ways to artificially bind this in JavaScript: apply (), bind () call (), which we’ll talk about later.

Object this

function foo() { console.log(this.a); } var obj1 = { a: 2, obj2: obj2 } var obj2 = { a: 4, foo: Foo //key property: foo references foo this binds to the object obj1} obj1.obj2.foo() // where is the function foo referenced and to which does this point this to obj2 a = 4Copy the code

The code analysis

We define function foo () and two objects obj1, obj2, with obj2 as the key property of obj1, obj2 as the object of value, and foo as the key property of obj2, referencing foo, and function foo as its value. Then call this foo() with obj1.obj2.foo (). It prints 4. Why is that?

[Implicit binding]

This is our implicit binding rule. When a function has a reference to a context object, it implicitly binds the function’s this binding above that context. Function foo () is added to obj2 as a reference property, but foo is not technically part of obj2, but when executed, foo () is called in obj2’s execution context, so you can say that the function is called “owning” or “containing” the function reference. So foo () ‘s this points to obj2, and the printout is 2

【 knowledge 】

The innermost layer of a method call is wrapped in a specified context and cannot be inserted into the middle of this layer if it is bound later. In the above example, foo () ‘s this already binds obj2. If obj2 is bound to another object as a whole, foo ()’ s this still refers to obj2.

[Implicit loss]

function foo(){ console.log(this.a); } var obj = {a:2, foo:foo // implicit binding} var bar = obj.foo // Function alias actually calls the function itself var a = 4 bar() // calls the global below aCopy the code

The code analysis

Analyzing the code above, we define an obj object and the function foo (), which refers to foo as a function, which is implicitly bound. We then define variables A and bar externally, so what will be the final print?

Var bar = obj. Foo (); var bar = obj. Foo (); var bar = obj. Foo (); So it’s going to print 4.

This can also happen in callback functions, so we should be careful not to step on holes!

[Explicit binding]

function foo() { console.log(this.a); } var obj = {a: 2,} foo.call(obj) // artificial bindingCopy the code

The call (), apply (), and bind () functions are used to specify the execution context of this.

The constructor

We all know that constructors go through a trilogy when creating an object

Constructor trilogy

The name property is passed. The implicit stereotype binding constructor of the object shows that stereotype 3 returns thisCopy the code

Let’s look at a simple example

function constructor(){

  this.a = 1;
  
}

var obj = new constructor();

console.log(obj.a); / / 1
Copy the code

When a function is used as a constructor, its this is bound to the new object being constructed when the new keyword is used. So it’s natural to print a 1.

conclusion

The variations of this are endless, and it took tens of thousands of programmers to figure them out. Even if I get bald, I can’t finish the story of this. The above is my shallow solution to this. In a word, whoever covers this has to be responsible for this, regardless of the strict mode.

I am xiaobai, shallow solution this, if there are mistakes, but also please point out, thank you!