JS 手写bind函数

先看一个bind函数的例子:

function fn1(a, b, c) {
    console.log('this', this); // { x: 100 }
    console.log(a, b, c); // 10 20 30
    return 'this is fn1';
}
const fn2 = fn1.bind({ x: 100 }, 10, 20, 30);
const res = fn2();
console.log(res); // this is fn1

如果我们要手写一个bind函数的话,我们需要知道bind拿了什么参数,干了什么:①接收一个对象(this);②接受n个参数;③返回函数。
那么需求我们知道了,如何实现呢?

首先fn1对于Function来说是Function的实例,这个没有问题吧。那么肯定有fn1.__proto__ === Function.prototypeFunction.prototype中是有callapply等函数的API,既然这样我们就用我们原型Function的方法~

我们不确定bind的参数传几个,我们所知道的只是第一个参数是this要指的对象,第二个一直到最后一个参数我们都不确定,所以我们在手写的时候没法一个一个接收参数,所以第一步我们要将第一个参数this对象和后面的参数分离。

下面是步骤:

  1. 先在函数原型上建立一个名为bind1的函数:
Function.proyotype.bind1 = function() {

}

  1. 将参数拆解为数组
    参数我们通过arguments获取,arguments可以获取一个函数的所有参数,不管你传1个还是传100个。但它是一个列表的形态(叫:类数组),不是数组,不好处理,所以我们要把它拆解为数组:
Function.proyotype.bind1 = function() {
    const args = Array.prototype.slice.call(arguments);
}

其中,sliceArray.prototype上的方法,这块可以理解为将arguments这个类数组赋予数组的slice功能。

  1. 获取this(数组的第一项)
Function.proyotype.bind1 = function() {
    const args = Array.prototype.slice.call(arguments);
    const t = args.shift();
}

shift方法将数组的第一项从数组中剔除,改变了原数组,返回了被剔除的这个数组~ 好,这下第一个参数有啦

  1. 找到fn1.bind(...)中的this,赋给self
Function.proyotype.bind1 = function() {
    const args = Array.prototype.slice.call(arguments);
    const t = args.shift();
    const self = this;
}

为了方便,好看,把this赋值给变量self。这块的this就是指:谁调用的这个bind1,就指向谁,比如一开始咱们的例子,如果fn1执行的话,就指向fn1

  1. 处理返回的函数
Function.proyotype.bind1 = function() {
    const args = Array.prototype.slice.call(arguments);
    const t = args.shift();
    const self = this;
    return function() {
        return self.apply(t, args);    
    }
}

结果我们是要输出绑定过的this函数,所以我们这里用apply方法,将之前获取的第一个this对象参数t,和后面的n个参数args传递进去,就是我们想要的结果啦。

检验一下:

function fn1(a, b, c) {
    console.log('this', this); // { x: 100 }
    console.log(a, b, c); // 10 20 30
    return 'this is fn1';
}
Function.proyotype.bind1 = function() {
    const args = Array.prototype.slice.call(arguments);
    const t = args.shift();
    const self = this;
    return function() {
        return self.apply(t, args);    
    }
}
const fn2 = fn1.bind1({ x: 100 }, 10, 20, 30);
const res = fn2();
console.log(res); // this is fn1

bind函数需要再次调用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 2021~01~07 越来越不想说话了,虽然看了整整一天别人的各种喜怒哀乐、历史和名人的各种轶事。 ...
    3352五彩阅读 126评论 0 0
  • 小伙伴们大家早上好啊!我是你们聪明勇敢有力气的孜孜。 距离12月四六级考试已经过去快一个月了,有不少的小伙伴都问孜...
    孜孜好学阅读 429评论 0 0
  • “一秒钟,太短,不够”,负罪自责悔恨,不能表达一个父亲的心情 张艺谋的《一秒钟》这段时间正在热映,它和不久前观看的...
    可以容忍阅读 129评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,575评论 16 22
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,616评论 0 11