如果忘了怎么实现call apply bind,就来看这篇文章

178 阅读1分钟

一、实现call

call 和 apply 和 bind其实就是改变函数的作用域。个人记忆法 叫的和绑定的只能一个个叫或者绑定,申请的话,可以一次申请多个。记这三个方法的 传参区别。bind函数调用,返回的是函数,并没有执行。

思路:整体的思路就是在调用的作用域下添加一个新函数并调用,然后删除。要处理context 为null时咋办,处理传参时候咋办,bind的时候还要想到返回的是个函数,并且可以被new,new了之后this的指向要变为 指向实例,还要用空函数来处理 prototype的继承。

call实现

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

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

    delete context1.fn
    return result;
}

// 测试一下
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));

apply实现

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

bind实现

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);