call、apply和bind的模拟实现

call()apply()的区别在于,call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组。
举例:

var func = function(arg1, arg2) {
     ...
};

func.call(this, arg1, arg2); // 使用 call,参数列表
func.apply(this, [arg1, arg2]) // 使用 apply,参数数组

一、call的模拟实现

我们先来看一个简单的例子。

var value = 1
var foo = {
	value: 4
}

function bar(){
	console.log(this.value)
}

bar.call(foo)  //4

通过上面代码实现,我们可以看出以下两点:

  • call() 改变了this指向
  • 函数bar执行了

call实现代码


Function.prototype.call_ = function (obj) {
    obj = obj ? Object(obj) : window;
    obj.fn = this;
    // 利用拓展运算符直接将arguments转为数组
    let args = [...arguments].slice(1);
    let result = obj.fn(...args);

    delete obj.fn
    return result;
};

二、apply的模拟实现

Function.prototype.apply_ = function (obj, arr) {
    obj = obj ? Object(obj) : window;
    obj.fn = this;
    let result;
    if (!arr) {
        result = obj.fn();
    } else {
        result = obj.fn(...arr);
    };

    delete obj.fn
    return result;
};

三、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");
    }

    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);  //使用arguments获取参数数组并作为 self.apply()的第二个参数

    var fNOP = function () {}; //创建一个空对象

    var fBound = function () {
        var bindArgs = Array.prototype.slice.call(arguments);   //此时的arguments指的是bind返回的函数传入的参数 获取返回参数的数组,并与之前的合并
      return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));  //使用apply绑定this
      // 当作为构造函数使用时,this指向实例,将绑定函数的this指向该实例,可以让实例获得来自绑定函数的值
      // 当作为普通函数使用时,this指向window,将绑定函数的this指向context
    }
  
  // 修改返回函数的prototype为绑定函数的prototype,实例就可以继承绑定函数原型中的值
    fNOP.prototype = this.prototype;  //空对象的原型指向绑定函数的原型
    fBound.prototype = new fNOP();  //空对象的实例赋值给fBound.prototype
    return fBound;  //使用return返回一个函数
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值