1. Implement Call

Call and apply and bind simply change the scope of a function. Personal memory method called and binding can only one call or binding, application, you can apply for more than one. Note the differences between the three methods. The bind call, which returns the function, is not executed.

The whole idea is to add a new function to the scope of the call, call it, and then delete it. If the context is null, if you pass an argument, if you bind, you have to think that you’re returning a function that can be new, and then you have to change the reference to this to an instance, and then you have to use empty functions to handle prototype inheritance.

The call to realize

Function.prototype.call2 = function (context) {
    var context1 = context || window;
    context1.fn = this;
    console.log(arguments)

    varresult = context1.fn(... ([...arguments].slice(1)));

    delete context1.fn
    return result;
}

// Test it
var value = 2;

var obj = {
    value: 1
}

function bar1(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}

bar1.call2(null); / / 2

console.log(bar1.call2(obj, 'kevin'.18));
Copy the code

Apply to realize

Function.prototype.apply2 = function(context, arr) {
    console.log(context);
    let context1 = context || window;
    console.log(this);
    context1.fn = this;
    let res;
    if(! arr) { context1.fn(); }else {
        let args = Array.prototype.slice(arguments.1);
        res = eval('context1.fn(' + args + ') ');
    }
    delete context1.fn;
    return res;
};
let  foo = {value: 21};
let bar = function() {
    console.log(this.value);
}
bar();
bar.apply2(foo);
//undefined
//VM1169:2 {value: 21}
/ / VM1169:4 ƒ () {
// console.log(this.value);
/ /}
//VM1169:18 21
Copy the code

The bind to realize

Function.prototype.bind2 = function(context) {
    if (typeof this! = ="function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }
    let self = this;
    let args = [...arguments].slice(1);
    let fNop = function(){};
    let fbind = function() {
        let argBind = [...arguments].slice();
        self.apply(this instanceof fNop ? this : context, args.concat(argBind));
        
    }
    fNop.prototype = this.prototype;
    fbind.prototype = new fNop();
    return fbind;
}
var value = 2;

var foo12 = {
    value: 1
};

function bar12(name, age) {
    this.habit = 'shopping';
    console.log(this.value);
    console.log(name);
    console.log(age);
}

bar12.prototype.friend = 'kevin';

var bindFoo = bar12.bind2(foo12, 'daisy');

var obj = new bindFoo('18');
// undefined
// daisy
/ / 18
console.log(obj.habit);
console.log(obj.friend);
Copy the code