What on earth is this

When a function is called, an execution context is created, with the following lifecycle:

Create {generate variable object, establish scope chain, make sure this points to} —–> execute {variable assignment, function reference, execute other code} —–> execute and wait to be reclaimed

We need to clear up the misunderstanding that this refers neither to the function itself nor to the lexical scope of the function. This is a property of the execution context that points to the execution context object. This is a binding that only happens when the function is called, and what it points to depends entirely on where the function is called.

2. Binding rules

To figure out what this refers to, you need to find where the function is called. The call location is where the function is called during execution, not where it is declared. Such as:

function a(){
  console.log('a');
}

function b(){
 console.log('b') a(); --> Call location} a(); --> Call locationCopy the code

1. Default binding

The default binding is also called a global binding.

In non-strict mode, when a function is executed, it is bound by default if it is called from an undecorated function reference.

When using the default binding, this points to a global object.

Here’s an example:

var a = 1;
function aa(){
  console.log(this. A); }function bb(){
  var a = 2;
  console.log(this.a);
  aa();
}

bb(); / / output 1, 1

Copy the code

2. Implicit binding (called as an object property)

When a function reference has a context object, the implicit binding rule binds this in the function call to that context object. Here’s an example:

function func() {
  console.log(this.a);
}

var obj = {
a: 2.b: 3 };

obj.func(); / / 2
Copy the code

Because this is bound to obj when func() is called, this.a is the same as obj.a.

It is important to note that only the previous or last level in the object attribute reference chain plays a role in the call location.

Implicit loss: Implicitly bound functions may in some cases lose bound objects and use the default binding (non-strict mode).

Here’s an example:

function func(fn){
 console.log(this.a);
}

function do(fn){
 fn(); Var obj = {a: 2, b: 3} var a = "global"; do(obj.func); // globalCopy the code

Parameter passing is essentially an implicit assignment. Fn is a reference to obj.func, but it refers to the function itself. So fn() does not have any modifier function calls in front of it, so the default binding is used.

This is especially noticeable when the callback function loses the this binding.

3. Explicitly bind with call and apply

If we want to force a function call on an object rather than include a function reference inside the object, we can use call or apply. Most functions can use these two methods.

The first argument to both methods is an object to be bound to this, and the second argument to be passed to the executing function.

Here’s an example:

function func{
 console.log(this.a);
}

var obj = {
 a:2
}

func.call(obj); // bind this to obj.

Copy the code

4. New binding

In javascript, constructors are simply functions that are called when the new operator is used. They don’t belong to a class, they’re just ordinary functions called by the new operator.

When a function is called with new, the new object is bound to this of the function call.

Here’s an example:

function aa(a){
 this.a = a;
}
var bb = new aa(2);
console.log(bb.a); / / 2
Copy the code

When aa() is called with new, a new object is constructed and bound to this in the aa() call.

Priority

Now we know that there are these binding rules, but what if there are multiple rules for a particular invocation location, so we need to prioritize those rules.

The following priorities are in descending order:

1. New binding.

2, call, apply call binding.

3. Binding is invoked by context, that is, implicit binding.

4. Default binding: bind to undefined in strict mode, otherwise bind to global object.

4. Exception arrow functions

Instead of using function, arrow functions are defined using arrows. Instead of using the four rules of this, arrow functions inherit the this binding of outer function calls. It is important to note that the binding of arrow functions cannot be changed!

Here’s an example:


function aa(){
 return (a) = > {
 console.log(this.a); }}var obj_1 = {
 a:1
}

var obj_2 = {
 a:2
}
var ss = aa.call(obj_1) / / 1
ss.call(obj_2) / / 1
Copy the code

The aa() function this is bound to obj_1, so the arrow function is bound to obj_1.

Ps: Welcome to point out any mistakes.

Reference:

Javascript You Don’t Know