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!