js手写bind

首先解释一下bind:

bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。(来自于 MDN )

给个例子:

var value = 'v in window';
function func() {
    console.log(this.value);
}
var obj = {
    value: 'v in obj'
};
func(); //v in window
var newFunc = func.bind(obj);
newFunc(); //v in obj

用法类似call和apply,调用返回的newFunc函数类似调用func.call(obj)或者func.apply。
根据这个原理,手写一个bind2:

var value = 'v in window';
function func() {
    console.log(this.value);
}
var obj = {
    value: 'v in obj'
};
Function.prototype.bind2 = function (obj) {
    var that = this;
    return function () {
        that.apply(obj); //call和apply都可以,这里用apply主要是为了方便后面处理带参数的情况
    }
};
func(); //v in window
var newFunc = func.bind2(obj);
newFunc(); //v in obj

bind2返回一个函数,调用这个函数时,that指向之前的func,相当于func.apply(obj),实现了bind功能
处理一下带参数的情况:

var value = 'v in window';
function func() {
    arguments = [].splice.call(arguments, 0); //这一句是把参数转成数组,因为arguments不是数组,输出的时候容易观察
    console.log(arguments);
    console.log(this.value);
}
var obj = {
    value: 'v in obj'
};
Function.prototype.bind2 = function (obj) {
    var that = this;
    var args = [].splice.call(arguments,1);
    return function () {
        that.apply(obj,args);
    }
};
func(1,2,3); 
//[1,2,3]
//v in window
var newFunc = func.bind2(obj,1,2,3);
newFunc();
//[1,2,3]
//v in window

官方bind还有一个特点:

var value = 'v in window';
function func() {
    arguments = [].splice.call(arguments, 0); //这一句是把参数转成数组,因为arguments不是数组,输出的时候容易观察
    console.log(arguments);
    console.log(this.value);
}
var obj = {
    value: 'v in obj'
};
var newFunc = func.bind(obj,1,2,3);
newFunc(4,5,6); 
//[1, 2, 3, 4, 5, 6]
//v in obj

如果给newFunc传参数,他可以把参数拼接起来,修改一下

Function.prototype.bind2 = function (obj) {
    var that = this;
    var args = [].splice.call(arguments,1);
    return function () {
        var newArgs = [].splice.call(arguments,0); //将newFunc的参数变成数组
        that.apply(obj,args.concat(newArgs)); //将上面的数组和之前的参数数组结合
    }
};

处理一下返回的函数被作为构造函数的情况:

Function.prototype.bind2 = function (obj) {
    var that = this;
    var args = [].slice.call(arguments,1);
    var func =  function () {
        that.apply(this instanceof func ? this : obj,args.concat([].splice.call(arguments,0))); //用来判断是不是作为构造函数:this instanceof func === true是则是构造函数
    };
    fNOP.prototype = this.prototype; //利用空函数fNOP实现继承原型链同时又不改变原函数的原型链
    fbound.prototype = new fNOP();
    return func;
};

最后处理一下兼容问题:

Function.prototype.bind2 = function (obj) {
    if (typeof this !== "function") { //不是函数不能调用bind方法
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }
    var that = this;
    var args = [].slice.call(arguments,1);
    var func =  function () {
        that.apply(this instanceof func ? this : obj,args.concat([].splice.call(arguments,0))); //用来判断是不是作为构造函数:this instanceof func === true是则是构造函数
    };
    fNOP.prototype = this.prototype; //利用空函数fNOP实现继承原型链同时又不改变原函数的原型链
    fbound.prototype = new fNOP();
    return func;
};
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值