JavaScirpt 的 bind 函数究竟做了哪些事
文章原地址: https://github.com/catchonme/blog/issues/2
ES5 实现 bind 函数如下Function.prototype.bind=function(that){
varself=this,
args=arguments.length>1?Array.slice(arguments,1):null,
F=function(){};
varbound=function(){
varcontext=that,length=arguments.length;
if(thisinstanceofbound){
F.prototype=self.prototype;
context=newF;
}
varresult=(!args&&!length)
?self.call(context)
:self.apply(context,args&&length?args.concat(Array.slice(arguments)):args||arguments);
returncontext==that?result:context;
};
returnbound;
}
测试 1varbar=function(){
console.log(this.x)
}
varfoo={
x:3
}
varfunc=bar.bind(foo);
func();// 3
bar 函数绑定 foo 中的 x 值, 然后输出 3
bind 函数中最主要的是 bound 函数, bound 函数做了哪些事呢?
首先 context 存储传入的 that 到 context 中, 判断
this instanceof bound
, 那什么时候
this instanceof bound == true
呢? 在测试 1 中的案例中,
this instanceof bound
为 false , 打印此时的 this 输出
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...}
, 发现是 window 对象, 因为 foo 本身就是在 window 对象中.
所以此时直接执行 self.call(context) , 返回执行的结果
3
, 就是我们测试 1 中的结果.
那什么时候
this instanceof bound == true
呢, 而且此时还需要使用空函数 F 来获取主函数的 prototype ,
答案是实例化, 什么时候实例化呢?
测试 2varbar=function(){
console.log(this.x)
}
bar.prototype.name=function(){
this.name='name';
}
varfoo={
x:3
}
varfunc=bar.bind(foo);
varnewFunc=newfunc;// undefined
newFunc.name();// name
对 bar.bind(foo) 进行实例化, 此时因为进行了 new 操作, new 操作做了什么呢, 参考 new 操作符里面到底发生了什么? https://segmentfault.com/q/1010000005141424 所以此时的 this 为新生成的 bound {} 对象, constructor 为 bound 函数, 所以此时
this instanceof bound == true
那为什么 bar.bind(foo) 把 foo 对象传递的时候, 没有输出
3
而是 undefined 呢? 也是因为 new 操作, 当前的上下文已经是新生成的 newFunc 函数了. 而且当
this instanceof bound == true
时, 会把 bar 的 prototype 赋给 F 函数, 而 bound 函数返回的是 new F , 所以这时 bar 的 prototype 也赋给 newFunc 了.
我们看看 ES6 的操作, 结果和上述例子是一样的.varbar=function(){
console.log(this.x)
}
bar.prototype.name=function(){
console.log('name')
}
varfoo={
x:3
}
varfunc=bar.bind(foo);
func();// 3
// 实例化
varnewFunc=newfunc;// undefined
newFunc.name();// name
总结:
所以 bind 函数总共做了哪几件事呢?
没有实例化时, 将传入对象的参数引用到当前函数, 执行当前函数, 返回结果
实例化时, 使用 new 操作生成新函数, 原函数的 prototype 赋给新函数, 执行新函数, 并返回新函数
来源: https://juejin.im/post/5ae2620a51882567336a7194