This is the fifth day of my participation in the August Wen Challenge.More challenges in August

1. Why use this?

  • This provides a more elegant way to implicitly pass an object reference.
function identify() { return this.name.toUpperCase(); } function speak() { var greeting = "Hello, I'm " + identify.call( this ); console.log( greeting ); } var me = { name: "Kyle" }; var you = { name: "Reader" }; identify.call( me ); // KYLE identify.call( you ); // READER speak.call( me ); // Hello, I'm KYLE Speak. Call (you); // Hello, this is READECopy the code

This code can reuse the identify() and speak() functions in different context objects (me and you) without writing a different version of the function for each object.

If you don’t use this, you need to explicitly pass in a context object to identify() and speak().

function identify(context) { return context.name.toUpperCase(); } function speak(context) { var greeting = "Hello, I'm " + identify( context ); console.log( greeting ); } identify( you ); // READER speak( me ); / / hello, I am KYLECopy the code

2. This four binding rules

This keyword is automatically defined in the scope of all functions.

Note: The orientation of this is not determined when the function is created, but only when it is called.

When we find this point, we need to find the call location first, and then determine which binding rule conforms to, and pay attention to the priority of the binding rule.

2.1 Default Binding

When the calling object of a function cannot be found,

  • Non-strict mode: function this refers to the global object Window.
  • In strict mode, this refers to undefined.

Note: For the default binding, what determines the this binding object is not whether the calling position is in strict mode, but whether the function body is in strict mode.

Example 1: A function call is preceded by no object

function sayHi(){
    console.log('Hello,'.this.name);
}
    var name = 'YvetteLau';
    sayHi();
    
// 'Hello,' YvetteLau
Copy the code

2.2 Implicit binding

If you call a function from an object, this points to the object that last called it.

Implicit loss

1. Assign obj.fn() to a variable

Although bar is a reference to obj.foo, it actually refers to the foo function itself, so bar() at this point is really a function call without any decorations, so the default binding is applied.

In the following example, this of o.foo is implicitly bound to the o object, and bar refers to the o.foo function itself, so bar() is actually a function call without any decorations, so the default binding rules are used:

var o = {
    a: 1,
    foo() {
        console.log(this.a)
    }
}
​
var bar = o.foo
​
o.foo() // 1
bar()   // undefined
Copy the code

2. Assign obj.fn() to the function parameter

Argument passing is essentially an implicit assignment, so when we pass in a function, we get an implicit assignment. In this example, bar(o.foo) actually uses implicit assignment: callback = O.foo, as in the previous example, we directly refer to the o.foo function itself, thus resulting in implicit loss:

function bar(callback) {
    callback()
}
​
var o = {
    a: 1,
    foo() {
        console.log(this.a)
    }
}
​
bar(o.foo) // undefined
Copy the code

3. This in the setTimeOut function

Example 2: setTimeOut contains a function that has no object to call when it is executed, so it is bound by default.

btn.onclick = function(){
    setTimeout(function(){
        console.log(this);
    },0)
}
btn.onclick();

// window
Copy the code

Although the onclick function is called by the BTN object, the contents of the setTimeout function are not executed immediately when the BTN object calls the onclick function. When the setTimeout function is executed, the setTimeout function cannot find the calling object, and then the default binding is changed. In non-strict mode, The this in the setTimeout function points to the window.

The setTimeOut task is a macro task and is executed in the next event loop. See juejin.cn/post/693532…)

2.3 Displaying Binding

We sometimes want to force the binding of this to a function by using the call() and apply() methods;

Call (object to bind this, argument 1, argument 2…)

Apply (the object to which this is bound, [parameter 1, parameter 2… )

Hard binding

function foo() { console.log( this.a ); } var obj = { a:2 }; var bar = function() { foo.call( obj ); }; bar(); // 2 setTimeout( bar, 100 ); // 2 // A hard-bound bar cannot change its this bar.call(window); / / 2Copy the code

We created the function bar() and manually called foo.call(obj) inside it, forcing foo’s this to be bound to obj. No matter how bar is later called, it will always manually call foo on obj. This binding is explicitly forced and is therefore called hard binding.

Hard binding ES5API

bind(..) Returns a new hard-coded function that sets the argument to the context of this and calls the original function.

If null/undefined is passed during hard binding, the hard binding is ignored and the default binding rules are used.

2.4 the new binding

When a function is called with the new operator, the function is called by the constructor.

The new operator does what it does when calling a function:

  • A brand new object is created or constructed
  • The new object will be connected by the implementation [[prototype]]
  • In the functionthisIt’s going to point to this new object
  • If the called function does not returnnewThe function call in the expression automatically returns the new object

3. Priority of the binding rule

New Binding > Explicit Binding > Implicit Binding > Default binding

To determine this:

  1. Is the function called in new (new binding)? If so, this binds to the newly created object.
  2. Is the function called by call, apply (explicit binding), or hard binding? If so, this binds to the specified object.
  3. Is the function called in a context object (implicitly bound)? If so, this binds to the upper context object.
  4. If neither, use the default binding. If in strict mode, it is bound to undefined, otherwise it is bound to global objects.

Arrow function

Arrow functions cannot use the above rules. This is determined by the outer (function or global) scope.

The arrow function’s this refers to this when its outer scope is called.

The arrow function created inside foo() captures foo() ‘s this when called. Since foo() ‘s this is bound to obj1, and bar (which references the arrow function)’ s this is bound to obj1, the binding of the arrow function cannot be modified. (Neither does New!)

Function foo() {return (a) => {//this inherits from foo() console.log(this.a); }; } var obj1 = { a:2 }; var obj2 = { a:3 }; var bar = foo.call( obj1 ); bar.call( obj2 ); // 2, not 3Copy the code

The arrow function inherits the this binding of the outer function call (whatever this is bound to).

Reference:

JavaScript you don’t know