JS面试题:call,apply,bind区别

395 阅读2分钟

1. 共同点

三者共同点都是改变函数内部this指向的方法

2. call用法

    var a = 2;
    var b = 2;
    function func() {
      console.log(this.a, this.b)
    }
    let obj = { a: 1, b: 1 }
    func.call(obj)
    func.call()

输出结果:

1 1
2 2

解析:

  1. call的第一个参数是更改后的this指向对象,如果第一个参数不填,在非严格模式下,指向的是全局;但是在严格模式下,指向的就是undefined了,所以得注意一下
  2. func.call(obj)中,this指向变化了,指向了obj,所以输出的结果是1 1
  3. func.call()中,在非严格模式下,默认改变了this指向到全局,所以输出2 2

3. call和apply区别

call和apply唯一的区别就是,传参形式不一样,call是一个个写入传进去,而apply是用一个数组包起来传进去

obj.call(thisObj, arg1, arg2, …);
obj.apply(thisObj, [arg1, arg2, …]);

4. call和bind的区别

call和bind语法完全一模一样,唯一不同的是call和apply是立即执行;而bind并不是立即执行,要执行得绑定之后,再去调用这个函数

    var a = 2;
    var b = 2;
    function func() {
      console.log(this.a, this.b)
    }
    let obj = { a: 1, b: 1 }
    func.bind(obj)()
    // 输出结果:1 1

5. 总结

  1. call,apply,bind都是改变函数this指向的
  2. call和apply用法基本上一致,唯一不同点是apply传参是以数组的方式传入,而call是一个个传入
  3. bind用法和call基本上一致,唯一不同的是call和apply是立即执行的,而bind不是立即执行

6. 面试真题

    var a = 1;
    function fn1() {
      var a = 2;
      console.log(this.a + a)
    }
    function fn2() {
      var a = 10;
      fn1();
    }
    fn2()
    var Fn3 = function () {
      this.a = 3
    }
    Fn3.prototype = {
      a: 4
    }
    var fn = new Fn3()
    fn1.call(fn)

输出结果:

 3 (1+2)
 5 (3+2)

讲解:

  1. 执行fn2()的时候,fn1中的this指向是全局,相当于是1+2=3;则输出结果是3
  2. fn1通过call改变this指向到了Fn3,此时可以在Fn3上一层层找到a,此时在构造函数中就有a所以此时是3+2=5;如果构造函数中没有对this.a赋值,则会沿着原型链一层层找上去,找到在 Fn3.prototype中有声明了一个a,所以如果构造函数中没有对this.a进行赋值,则此时的结果应该会是4+2=6