bind和call的笔试题,为什么用call和没用call执行的结果一样?

面试题是这样的:

var s = {
        s: 'student',
        getS:function(){
            console.log(this.s);
        }
};
var t = {
    s: 'teacher chen'
}
var getS = s.getS;
var getS1 = getS.bind(s);

正确的运行结果是:

getS1();  // student
getS1.call(t);  //student

var getS1 = getS.bind(s) 这一句的是说创建一个新函数,并且通过bind,将新函数的this绑定到对象s。输出student没错。但是,getS1.call(t),不是通过call方法,将this绑定到对象t了吗?为嘛输出的仍然是student而不是teacher chen 呢?

阅读 2.7k
4 个回答

对这个问题很感兴趣,查了一些资料
以下是 MDN 里 bind 的 Polyfill , 可以看出来 bind 返回的函数只有用 new 方法当做构造函数调用时才会改变 this, 其他情况下的 this 一直是绑定的那个

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');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          // this instanceof fNOP === true时,说明返回的fBound被当做new的构造函数调用
          return fToBind.apply(this instanceof fNOP
                 ? this
                 : oThis,
                 // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    // 维护原型关系
    if (this.prototype) {
      // Function.prototype doesn't have a prototype property
      fNOP.prototype = this.prototype; 
    }
    // 下行的代码使fBound.prototype是fNOP的实例,因此
    // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
    fBound.prototype = new fNOP();

    return fBound;
  };
}

另外,还有 https://blog.csdn.net/learnin... 这位作者做了一些实验,结论是:对哪个函数使用bind()方法即改变这个函数的this值,和内置其参数,或者说像克里化一样理解,先预置好参数

new的情况就给楼上说的, 给你写一个差不多的简单例子就知道了

function fn(){
  console.log(this)
}

var test = function(){
 //我的this没用到 改变我也没用
  return fn.call('123')
}

test();//123

test.call('aaa');//123

因为 bind 的绑定级别高于 call/apply 。

在MDN上复习this的用法。里面是这说bind的:
“调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。”
对照我给的例子,var getS1 = getS.bind(s); getS1和getS的函数体和作用域相同,但是getS1的this被永久绑定在对象s上,即使用call方法也无法改变this的值。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题