美文网首页程序员
为什么连续bind只有第一次的绑定值生效

为什么连续bind只有第一次的绑定值生效

作者: Eileen_1d88 | 来源:发表于2019-10-10 07:27 被阅读0次

今天面试今日头条,被问到这样一段代码

function func(...args) {
        console.log(this, ...args)
}
func.bind({a:1}).bind({b: 1})(2,3)

结果是:

{a: 1} 2 3

为什么呢?MDN中给出的Polyfill是这样的, 虽然和标准实现有些差别,但基本的功能是一样的,我们可以用它来了解bind的实现原理:

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }
    // 有朋友表示不知道这里为什么这样写,其实原因是
    // arguments是一个类数组,它本身看起来像一个数组,但是它不没有数组的方法
    // 那么这里我们要取出arguments里第一个参数往后的参数的话,就需要给这个arguments赋予一个slice方法
    // Array.prototype.slice.call(arguments)就是当slice执行时,this指向了arguments,
    // 就相当于arguments.slice()
    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
            console.log('this', this);
            console.log('oThis', oThis);
          // this instanceof fBound === true时,说明返回的fBound被当做new的构造函数调用
          return fToBind.apply(this instanceof fBound
                 ? this
                 : oThis,
                 // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    // 维护原型关系
    if (this.prototype) {
      // 当执行Function.prototype.bind()时, this为Function.prototype 
      // this.prototype(即Function.prototype.prototype)为undefined
      fNOP.prototype = this.prototype; 
    }
    // 下行的代码使fBound.prototype是fNOP的实例,因此
    // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
    fBound.prototype = new fNOP();
    return fBound;
  };
}

执行

function test(...args) {
  console.log(this, ...args);
}
test.bind({a:1}).bind({b: 1})(2,3);

可以看到控制台的打印:


image.png

根据这个打印结果以及bind的实现,我们可以看到,bind的实现方式是一个柯里化的函数,每次的绑定就相当于:

function test(...args) {
  console.log(this, ...args);
}
function f1() {
  return test.apply({a: 1})
}
function f2() {
  return f1.apply({b: 1})
}
f2()

把f1换成第一次bind,f2换成第二次bind,就可以明白为什么最后只有第一个bind生效,因为执行到最后时,传进去的oThis就是第一次绑定的对象。
ps:关于函数的柯里化如何实现,我还没有太理解,希望下次能明白

相关文章

  • 为什么连续bind只有第一次的绑定值生效

    今天面试今日头条,被问到这样一段代码 结果是: 为什么呢?MDN中给出的Polyfill是这样的, 虽然和标准实现...

  • Vue.js 笔记

    v-bind:绑定属性 v-bind绑定属性,v-bind:属性名=‘值’,v-bind :属性名=‘值’ v-m...

  • 分析 MDN bind方法的Polyfill

    一、bind 方法介绍 bind 方法创建一个新的绑定函数 bind 方法重新绑定原函数的 this 值 在调用绑...

  • vue2.x(指令v-bind)

    v-bind 缩写 使用v-bind来绑定css样式: 在绑定CSS样式是,绑定的值必须在vue中的data属性中...

  • Vue的常用指令

    v-bind: 用于绑定属性,通过v-bind:绑定过的属性,可以在属性值可以写表达式v-bind:可以用**: ...

  • v-bind绑定class和style

    用v-bind可以绑定class 用v-bind同样可以绑定stylekey是属性,value对应属性对应的值。 ...

  • Vue入门指南(3)

    属性绑定 v-bind:给属性绑定对应的值 这时候a的href属性值就是我们希望的值。如果想将标签绑定,可以采用下...

  • Vue2学习笔记:vue模板语法

    一、插值(数据绑定) ①绑定纯文本{{msg}} ②绑定纯html v-html ③绑定属性 v-bind ④绑...

  • Function(){}.bind()

    bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入...

  • Vue 指令的使用(一)常用指令

    一、 v-bind 变量绑定 1.使用场景: 动态绑定属性的值 2.使用方法: 属性前添加v-bind:即可 v...

网友评论

    本文标题:为什么连续bind只有第一次的绑定值生效

    本文链接:https://www.haomeiwen.com/subject/kcrnpctx.html