JS 多次执行bind
有关于bind/call/apply的文章请移步:https://www.soulferry.xyz/?p=551
首先bind的其实就是改变作用域之后返回一个可执行的函数。
这里是bind的实现方式
Function.prototype.mbind = function(ctx) {
if (typeof this !== 'function') {
throw new TypeError('need function')
}
var _this = this
var args = [...arguments].slice(1)
return function F() {
if (this instanceof F) {
return new _this(...args, ...arguments)
} else {
return _this.apply(ctx, args.concat(arguments))
}
}
}
注意bind内部其实用的是call或者apply将ctx做了重新绑定,先看一下下边的引申题目。
var one = function(){
console.log(this.x);
}
var two = {
x: 1
}
var three = {
x: 2
}
var fn = one.bind(two).bind(three);
fn(); /*打印结果为 1*/
var four = {
x: 3
}
var fn = one.bind(two).bind(three).bind(four);
fn(); /*打印结果为 1*/
/* 为什么呢? */
为什么是两次都为1?
两次都仍将输出 1 ,而非期待中的 2 和 3。原因是,在Javascript中,多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。
同理再看一下另外一个拓展题。
var a=function(){
console.log("a")
if(this){
this()
}
}
var b=function(){
console.log("b")
if(this){
this()
}
}
var c=function(){
console.log("c")
if(this){
this()
}
}
var d=a.bind(b)
var e=d.bind(c)
d()
e()
/* 执行结果为a、b、this类型错误 a、b、this类型错误 */
出现上面的结果其实也是预料之内的。
首先,d = a.bind(b)
d = function() {
console.log("a")
if(b){
b()
}
}
这里d()
的意思是将a的this绑定到b,然后执行。因此执行输出肯定是a, b
。因此a中的this()
实际上就等于b()
.但是当b中运行时,this的类型就已经是不是function了(此处的this没有指向所以是undefined),因此运行肯定是会报错的。
e = d.bind(c);
e();
同样的道理,这里会首先执行d函数,然后执行c函数,但是在执行d的时候this就已经是undefined了,肯定就不会继续向下执行了,因此也就仅仅只执行了d函数,输出了a, b。
将代码类型打印出来
var a=function(){
console.log("a")
console.log('a:', typeof this);
if(typeof this == 'function'){
this()
}
}
var b=function(){
console.log("b")
console.log('b:', typeof this);
if(typeof this == 'function'){
this()
}
}
var c=function(){
console.log("c")
console.log('c:', typeof this);
if(typeof this == 'function'){
this()
}
}
var d=a.bind(b)
var e=d.bind(c)
d()
e()
执行结果如下:
a
a: function
b
b: undefined
a
a: function
b
b: undefined