昨天搜了下bind怎么实现,你们都在说bind的特征啊啥的,没搜到,今天有人问起来,我反问他要咋搜,他和我说柯里化。柯里化!!!它的最经常使用的表现形式不就是传说中的闭包的其中一种嘛!!!segmentfault
I think! I can do it!!!我以为我能够尝试着实现一下。闭包
首先咱们来回想this指向的几种可能性:app
想一想咱们能够使用可能性1,先来写个aplly方法:dom
先写个实验用具:函数
function sum(a, b) {
return this.a + this.b
}
let obj1 = {
a: 11,
b: 7
}
let obj2 = {
a: 1,
b: 1,
}
复制代码
再写个第一版仿生myApply:post
function myApply(that, arg){ //接受that参数参数,做为将来this
that = JSON.parse(JSON.stringify(that)) //给作个深拷贝,不影响原来的对象
that.Fn = this //给对象设置属性Fn,让它等于咱们前面调用myApply的sum
return that.Fn(...arg) //用属性调用的方式执行函数,让this指向传入的that,放入参数
}
复制代码
但这么写有个问题,咱们但愿在sum里面对this进行操做的时候,做为this源的对象也跟着改动,因此咱们那么写:测试
function myApply(that, arg = []){
that = that!== null && typeof that === 'object'?that: {} //在this不为object时的处理
that.Fn = this
const result = that.Fn(...arg)
delete that.Fn //使用完以后对that下的Fn进行删除
return result
}
复制代码
完成后咱们将myApply放到Function的原型上并测试看看它:ui
Function.prototype.myApply = myApply
console.log(sum1.myApply(obj1)) //18
console.log(sum2.myApply(null, [2, 3])) //5
复制代码
到这里apply方法就算写完了。this
柯里化(curry):只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。spa
接下来咱们要用到柯里化形式的闭包来保存下bing函数调用时的this和传进来的参数,以便在返回函数中用到它们:
function myBind(that, ...arg) { //建立时保存bind中传进来的arg
const _Fn = this //保存sum函数
return function () {
const args = [...arg, ...arguments] //合并两次传递进来的参数
return _Fn.myApply(that, args) //调用sum函数的myApply方法
}
}
复制代码
和前面同样,将myBind放到Function的原型上,并测试它:
Function.prototype.myBind = myBind
const sum3 = sum1.myBind(obj1)
console.log(sum3()) //18
const sum4 = sum1.myBind(obj1).myBind(obj2)
console.log(sum4()) //18
const sum5 = sum2.myBind(obj1, 5)
console.log(sum5(6)) //11
复制代码