JS面试题:函数this指向问题

271 阅读2分钟

1. 解题思路

  1. 普通函数中,this是它的直接调用者,谁调用,this就指向谁
  2. 箭头函数,this指向跟外部作用域中this指向是同一个

记住上面这两点,我们就可以开始做题啦

2. 面试真题

题目1:

    var a = 1;
    function func1() {
      var a = 2;
      console.log(this.a + a)
    }
    function func2() {
      var a = 10;
      func1()
    }
    func2()

输出结果:3

讲解: func1中的this指向的是全局的,所以这边获取的this.a的值为1

题目2:

    var a = 1;
    var obj = {
      a: 2,
      func1: function () {
        console.log(this.a)
      },
      func2: () => {
        console.log(this.a)
      }
    }
    obj.func1()
    obj.func2()

输出结果:

2 1

讲解:

  1. func1是普通函数,所以谁调用就指向谁,obj.func1相当于就是obj调用func1,所以this指向全局,所以obj.func1()输出的是2
  2. func2是箭头函数,箭头函数的this跟外部作用域的this是一致的,func2外部作用域相当于就是obj的作用域,obj中的this就是全局的this,所以此时取到的值就是全局的a,值为1

题目3:

    const obj = {
      name: '小明',
      say() {
        console.log(`你好!${this.name}`)
      }
    }
    const func = obj.say;

    obj.say();
    func();
    setTimeout(obj.say, 100)
    setTimeout(func, 200)
    setTimeout(function () {
      obj.say()
    }, 300)
    setTimeout(() => obj.say(), 400)

输出结果:

      你好!小明
      你好!
      你好!
      你好!
      你好!小明
      你好!小明

解析:

  1. obj.say()直接调用,则是obj调用say,所以this指向obj,则可获取到obj中的name值,故而输出:你好!小明
  2. func()在全局调用,所以函数中的this指向的是全局,全局没有name值,所以输出:你好!
  3. setTimeout(obj.say, 100)中是把obj.say赋值给setTimeout中的第一个参数,并没有通过obj去调用say函数,所以此时内部的this指向的是全局,故而没有nam值,输出结果为:你好!
  4. setTimeout(func, 200)跟3中输出的结果是一样的,这边都指数函数的赋值,并没有真正调用,所以这里的this是setTimeout中的this,setTimeout中的this指向的是全局,故而没有name值,输出结果为:你好!
  5. 在setTimeout内部函数中,调用了obj.say(),故而此时this指向调用它的对象obj,所以输出:你好!小明
  6. 这里的setTimeout中也是obj.say()直接执行调用了,所以谁调用指向谁,故而这里指向obj,所以这边输出结果为:你好!小明

口诀:普通函数的this,谁调用就是谁;箭头函数this,跟外部作用域一致