Detailed explanation of this pointer

Detailed explanation of this pointer

concept

this is the running environment context of the current function / module. Is a pointer type variable. this in an ordinary function is pointed to by the binding confirmation only when it is called.

Calling the same function through different this can produce different results.

How to confirm the content of this binding?

Rules for this binding

1. Default binding

function a() {}
a();

When a function is called independently, it is a function reference without any decoration

  • In non strict mode, this points to the global object
var a = 'hello';
var obj = {
    a: 'world',
    foo: function () {
        console.log(this.a);
    },
};

let bar = obj.foo;
bar(); // hello is called directly when it is called. So it points to the global this
// obj.foo(); // world
  • In strict mode, this points to undefined. In strict mode, it is not allowed to point to global objects.
var a = 'hello';
var obj = {
    a: 'world',
    foo: function () {
        'use strict';
        console.log(this.a);
    },
};

let bar = obj.foo;
bar(); // An error will be reported because this is the undefined target
  • When a normal function is passed as a parameter, setTimeout and setinterval. In the non strict mode, this points to the global object.
var name = 'hello';

var person = {
    name: 'world',
    sayHi: sayHi,
};

function sayHi() {
    console.log(this); // person
    setTimeout(function () {
        // Points to a global object
        console.log(this.name); // hello
    });
}

person.sayHi();

2. Implicit binding

Contrary to the default binding, function calls are explicitly decorated,

var a = 'hello';
var obj = {
    a: 'world',
    foo: function () {
        console.log(this.a);
    },
};

// Whoever calls this function (foo) is this of this function
obj.foo();
  • In the case of chain call, this points to the nearest
function sayHi() {
    console.log(this.name);
}

var person1 = {
    name: 'hello',
    sayHi: sayHi,
};

var person2 = {
    name: 'world',
    friend: person1,
};

// The chain call points to the nearest point
person2.friend.sayHi();

Explicit binding

call apply bind to modify the this point of the function

Similarities and differences between call and apply

  • Change the point of this, and then execute the original function
  • The first parameter is bound to this in the function body as this. If the parameter fun.cal() is not passed, this will be bound to the global object in the non strict mode
func.call(this, arg1, arg2, ..., argn);
func.apply(this, [arg1, ..., argn])
// Only object tostring can return type
Object.prototype.toString.call(obj) === '[object Array]'
  • What happens if the first parameter of call passes basic types such as numbers or strings?
    Get string objects, numeric objects [Number: 1] [String: 'lubai'], etc

bind

The bind method will create a new function,
When this new function is called, the first parameter of bind will be used as this when the function runs, and a series of subsequent parameters will be passed into the function as its function before passing the arguments

var account = {
    name: 'hello',
    author: 'world',
    subscribe: function (subsc) {
        console.log(`${subsc} ${this.name}`);
    },
};
account.subscribe('Whisper'); // Whisper hello
var subsc1 = account.subscribe.bind({ name: 'name', author: 'author' }, 'subsc');
subsc1(); // subsc name (the priority of explicit binding is higher than that of implicit binding)

new

  1. Create an empty object
  2. The of an empty object\_\_ proto\_\_ The prototype that points to the prototype object
  3. Execute the original constructor with the new object as this
  4. return
function Study(name) {
    this.name = name;
}

var study = new Study('hello');

console.log(study.name);

5. Priority of this binding

new binding > explicit (bind, call, apply) binding > implicit binding (obj. Foo()) > default binding (foo())

// Explicit binding has higher priority than implicit binding
function foo(a) {
    // console.log(this.a);
    this.a = a;
}

var obj1 = {
    a: 2,
    foo: foo,
};

var obj2 = {
    a: 3,
    foo: foo,
};
// Implicit binding
obj1.foo(); // 2
obj2.foo(); //3

// Forcibly change the point of this
obj1.foo.call(obj2); // 3
obj2.foo.call(obj1); // 2
function foo(a) {
    // console.log(this.a);
    this.a = a;
}
var obj1 = {
    foo: foo,
};

var obj2 = {};

obj1.foo(2);
console.log(obj1.a); // 2

// Forcibly point the foo parameter to obj2
obj1.foo.call(obj2, 3);
console.log(obj2.a); // 3

// new points obj1 to bar, which is equivalent to bar.a = a, and does not change the object obj1
var bar = new obj1.foo(4);

console.log(obj1.a); // 2
console.log(bar.a); // 4
function foo(a) {
    this.a = a;
}
var obj1 = {};

// this executed by bind is changed to obj1
var bar = foo.bind(obj1);

bar(2);
console.log(obj1.a); // 2

var barNew = new bar(3);
// In the process of new, run the original constructor function foo(a) {this.a = a} with the new object as this
// The new object is barNew

console.log(obj1.a); // 2

console.log(barNew.a); // 3

Arrow function

  1. The arrow function does not have arguments
  2. The arrow function does not have a constructor (it does not have a constructor)
  3. There is no own this (the direction of this is determined by the position of the defined arrow function, while the ordinary function is determined only when it is called)

Topic exercise

  1. Topic 1

    var a = 123;
    function getA() {
     console.log(this.a) // undefined
    }
    
    getA()
var a = 123;
var obj = {
    a: 456,
    getA: function() {

        // console.log(this): this here points to obj
        function getAA() { // There is an independent this in it
            console.log(this.a) // undefined
        }
        getAA() // Default binding
    }
}
obj.getA() // undefined
  1. Topic 2

    var length = 10;
    function fn() {
     console.log(this.length)
    }
    var obj = {
     length: 5,
     method: function(fn) {
         // this = obj
         // fn is a parameter, and this with the function as the parameter points to the global.
         fn();  10
    
         // arguments{0:fn, 1: 1, length:2} is equivalent to implicit binding to fn object
         arguments[0]()
     }
    }
    obj.method(fn, 1)

Tags: Javascript Front-end this

Posted on Sun, 05 Dec 2021 00:36:09 -0500 by bruckerrlb