有关于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

 

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注