this Keyword is one of the most complex mechanisms in JavaScript. It is a very special keyword that is automatically defined in the scope of all functions. But even very experienced JavaScript developers have a hard time telling what exactly it points to.
What is this?
Points to the function itself?
Looking at the literal meaning, it is easy to think that this is pointing to the function itself. Is this really the case? We can look at an example.
function foo() { this.count = this.count ? this.count + 1 : 1; } for (let i = 0; i < 5; i++) { foo(); } console.log(foo.count); // undefined
As you can see, the output of foo.count is not the 5
we expected, but the 0
assigned at the beginning. In other words, this does not actually point to the function itself.
Point to scope?
Another common misunderstanding is that this points to the scope of the function.
function foo() { var a = 2; bar(); } function bar() { console.log(this.a); } foo(); // undefined
In this code, bar is run in foo, and the output of this.a
is undefined
. In other words, this is not pointing to the scope of the function.
It’s not this, it’s not that, what is this? During the execution of the function, an execution context (a record) will be created. This is an attribute in this context and is used during the execution process. The point of this depends on where the function is called.
The binding rules of this
There are four rules that can be followed for the binding of this, which will be introduced one by one below.
1. Default binding
Independent function call, in non-strict mode, points to window; in strict mode, points to undefined.
The independent functions mentioned here can be understood as general function calls except for the following three situations.
// 非严格模式 var name = 'Willem'; function foo() { console.log(this.name); } foo(); // Willem // 执行时启用严格模式 (function() { 'use strict'; foo(); // Willem bar(); // Cannot read property 'name' of undefined })(); // 函数体使用严格模式 function bar() { 'use strict'; console.log(this.name); }
In the above code, Willem is output in the normal environment, indicating that it is indeed the window object pointed to. One thing that needs special attention is: Pointing to undefined in strict mode refers to the fact that strict mode is enabled in the function body, not when it is called.
2. Implicit binding
Implicit binding refers to whether is owned or included by an object when the function is executed.
. In other words, when the function is running, it is not very clear whether it is run as an attribute of an object. Here is an example:
function foo() { console.log(this.a); } var a = 1; var obj = { a: 2, foo }; obj.foo(); // 2 var obj2 = { a: 3, obj }; obj2.obj.foo(); // 2
In the example, foo is regarded as a member of obj At this time, obj serves as the context of the function, and this points to obj. this.a
is equivalent to obj.a
. In the object property chain call, only the last layer will affect the calling position, which means that the last layer will affect the this point.
Many front-end friends may have seen this question during interviews:
function foo() { console.log(this.a); } var a = 1; var obj = { a: 2, foo }; var bar = obj.foo; bar(); // 1
This is the most common problem with implicit binding, Implicit loss: hidden Functions bound in this way will lose the binding object. Although bar is a reference to obj.foo, it actually refers to the foo function itself. The bar function is a call to an independent function. Refer to the first item. At this time, this points to window|undefined
.
There is also a classic callback function's this pointing problem that is also implicitly lost.
function foo() { console.log(this.a); } function doFoo(fn) { fn(); } var a = 1; var obj = { a: 2, foo }; doFoo(obj.foo); // 1
Summary: In implicit binding, when assigning values (callbacks are implicit assignments), special attention needs to be paid to the issue of implicit loss.
3. Display binding
Function in JavaScript provides two methods call
and apply
, the first parameter passed in is An object will bind this to this object. If a primitive value (string, number, Boolean) is passed in, it will be converted into its object form (new String(), new Boolean(), new Number()).
function foo() { console.log(this.a); } var obj = { a: 1 }; foo.call(obj); // 1
Although we can use call
and apply
to explicitly specify the point of this, there will still be a problem of losing binding. It can be solved through the so-called hard binding (bind function)
, so I won’t go into details here.
4. new
The last thing I want to introduce is to use new
to modify the binding of this. It should be clearer for children who have manually implemented new. In js new is completely different from new in other languages.
new execution process:
- Create an empty object
- The current empty object performs prototype docking
- Return the function execution result or the current empty object
function Foo(a) { this.a = a; } var bar = new Foo(2); bar.a; // 2
When using new to call a function, we will construct a new object and bind it to this in the function call.
Priority
Finally, let’s briefly talk about the priority relationship: new > display binding > implicit binding > default binding.
Recommended study: "javascript basic tutorial"