先看一个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.prototype
。Function.prototype
中是有call
、apply
等函数的API,既然这样我们就用我们原型Function
的方法~
我们不确定bind的参数传几个,我们所知道的只是第一个参数是this
要指的对象,第二个一直到最后一个参数我们都不确定,所以我们在手写的时候没法一个一个接收参数,所以第一步我们要将第一个参数this
对象和后面的参数分离。
下面是步骤:
- 先在函数原型上建立一个名为
bind1
的函数:
Function.proyotype.bind1 = function() {
}
- 将参数拆解为数组
参数我们通过arguments
获取,arguments
可以获取一个函数的所有参数,不管你传1个还是传100个。但它是一个列表的形态(叫:类数组),不是数组,不好处理,所以我们要把它拆解为数组:
Function.proyotype.bind1 = function() {
const args = Array.prototype.slice.call(arguments);
}
其中,slice
是Array.prototype
上的方法,这块可以理解为将arguments
这个类数组赋予数组的slice
功能。
- 获取this(数组的第一项)
Function.proyotype.bind1 = function() {
const args = Array.prototype.slice.call(arguments);
const t = args.shift();
}
用shift
方法将数组的第一项从数组中剔除,改变了原数组,返回了被剔除的这个数组~ 好,这下第一个参数有啦
- 找到
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
。
- 处理返回的函数
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函数需要再次调用
网友评论