The js function explicitly changes the three methods to which this refers: the apply, call, and bind methods. For other ways to change the direction of this, see: juejin.cn/post/697068…

Rules for using the three methods

1. Use of the three methods

let per1 = {
    name: "Rose".age: 14.introduce: function(){
        console.log(I call `The ${this.name}This year,The ${this.age}Years old. `); }}let per2 = {
    name: "Jack".age: 15
}
console.log(per1.introduce.call(per2));  // My name is Jack. I am 15 years old.
console.log(per1.introduce.apply(per2));  // My name is Jack. I am 15 years old.
console.log(per1.introduce.bind(per2)());  // My name is Jack. I am 15 years old.
Copy the code

As you can see from the examples above, the call() and apply() methods call the function directly, while the bind() method generates a function.

If null is used after all three methods, this points to a global object, otherwise it points to an empty object (pointing to an empty object may not be an exact description, but the explanation makes sense).

let per1 = {
    name: "Rose".age: 14.introduce: function(){
        console.log(I call `The ${this.name}This year,The ${this.age}Years old. `); }}window.name = "window";
window.age = Awesome!;
console.log(per1.introduce.call(null));  // My name is Window. I am 666 years old.
console.log(per1.introduce.apply(123));  // My name is undefined and I am undefined.
console.log(per1.introduce.bind("abc") ());// My name is undefined and I am undefined.
Copy the code

2. Three ways of parameter transmission

let per1 = {
    fn: function(fm, to){
        console.log(I come from `${fm}Be on the way${to}. `); }}let per2 = {};
console.log(per1.fn.call(per2, "Wuhan"."Hangzhou"));  // I come from Wuhan and am going to Hangzhou.
console.log(per1.fn.apply(per2, ["Wuhan"."Hangzhou"]));  // I come from Wuhan and am going to Hangzhou.
console.log(per1.fn.bind(per2, "Wuhan"."Hangzhou") ());// I come from Wuhan and am going to Hangzhou.
console.log(per1.fn.bind(per2)("Wuhan"."Hangzhou"));  // I come from Wuhan and am going to Hangzhou.
console.log(per1.fn.bind(per2, "Wuhan") ("Hangzhou"));  // I come from Wuhan and am going to Hangzhou.
Copy the code

As you can see from the example above, call() passes all the parameters except the first one, just as it passes the original fn() method. The apply() method is different, passing in an array directly as arguments to fn(). The bind() method takes arguments that combine the parameters of the two functions. For details, see the bind() implementation below.

Three methods of implementation

1, call ()

Function.prototype.call_ = function(obj = window. args) {
    // first check whether obj is an object, otherwise point to an empty object
    if(typeofobj ! = ="object" && typeofobj ! = ="function") {
        obj = {};
    }
    
    // Add attributes to obj, avoid duplicate attribute names, use Symbol
    const fn = Symbol("fn");
    obj[fn] = this;
    
    // Execute the function
    constres = obj[fn](... args);// Clear the new fn attribute
    delete obj[fn];
    // Returns the result of the function execution
    return res;
}
Copy the code

2, the apply ()

Function.prototype.apply_ = function(obj = window, args) {
    // first check whether obj is an object, otherwise point to an empty object
    if(typeofobj ! = ="object" && typeofobj ! = ="function") {
        obj = {};
    }
    
    // Add attributes to obj, avoid duplicate attribute names, use Symbol
    const fn = Symbol("fn");
    obj[fn] = this;
    
    // Execute the function
    constres = obj[fn](... args);// Clear the new fn attribute
    delete obj[fn];
    // Returns the result of the function execution
    return res;
}
Copy the code

3, the bind ()

Function.prototype.bind_ = function(obj = window. args) {
    // first check whether obj is an object, otherwise point to an empty object
    if(typeofobj ! = ="object" && typeofobj ! = ="function") {
        obj = {};
    }
    // Save this by self
    const self = this;
    
    return function F(){
        // Consider the case of new
        if (this instanceof F) {
            return newself(... args, ... arguments); }returnself.apply(context, [...args, ...arguments]); }}Copy the code