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函数需要再次调用

你可能感兴趣的:(JS 手写bind函数)