JavaScript 中对 this 指向的理解

168 阅读3分钟

对 this 指向的理解

上周卓动的面试中,面试官提到了普通函数和箭头函数的区别,当时面试前准备的很不充分,是这么回答他的" 箭头函数和普通函数的最明显区别就是在代码上面的书写格式,箭头函数与普通函数写法上比起来更加简洁,其次是二者当中的 this 关键字指向不同(当时其实我是不知道二者的 this 指向具体有哪些不同的,最后面试官让我具体展开说说,我就直接寄了) "后面回来只能狠狠滴恶补。

this 的指向:

普通函数:

ES5 中,或者狭义一点,在普通函数当中,this 关键字指向的永远都是 "最后调用它的那个对象",最简单的例子:

var name = 'GGBond';
function fn() {
  var name = 'PandaGuo';
  console.log(this.name);
}
fn(); // GGBond

上述代码中,最后调用函数 fn 的地方是 fn(),而在非严格模式下,函数调用没有前缀的情况下,会默认绑定指向全局对象** window**,所以此刻的 fn() 就相当于 window.fn(),那么最后调用的对象就是 window

再对上述代码进行部分修改:

var name = 'GGBond';
  var student = {
    name: 'PandaGuo',
    fn: function() {
      console.log(this.name);
    }
  }
​
  var fn2 = student.fn;
​
  student.fn();  // PandaGuo
  window.student.fn();  // PandaGuo  
  fn2();  // GGBond

上述代码中,student.fn() 表明了前面的调用对象是 student,所以 this 指向会隐式绑定到 student 上;而 window.student.fn() 当中,无论前面调用的对象有多少个,都指向最后一个调用对象,所以这里的 this 也是隐式绑定到最后一个对象 student 上;对与 fn2() 为何最终打印出来的是 "GGBond" ?其实这里面有坑:虽然将 student 对象当中的 fn 方法 赋值给 fn2,但是没有进行调用,根据上述 " this 关键字指向永远都是最后调用它的那个对象 " ,fn2 没用调用,所以 fn 方法最后的调用对象还会是 window

再对代码进行部分修改:

  var name = 'GGBond';
  var student = {
    // name: 'PandaGuo',
    fn: function() {
      console.log(this.name);
    }
  }
  student.fn();  // undefined

student 对象中的 name 属性注释掉,最终 fn 方法打印出来的是 undefined,因为 " this 关键字指向永远都是最后调用它的那个对象 ",所以最终是 student 对象调用了 fn 方法,而 student 中没有对 name 进行定义,所以最终输出结果为 undefined

箭头函数:

在 ES6 的箭头函数当中没有自己的 this 绑定,它会继承上一层作用域的 this 对象,其 this 的指向取决于函数定义时的上下文环境,而不是函数调用时的环境,也就是说,当箭头函数被定义时,其 this 的指向就已经确定了(静态化),如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this。

举例:

  var name = 'GGBond';
  var student = {
    name: 'PandaGuo',
    fn: function() {
      setTimeout(() => {
        console.log(this.name);
      }, 1000)
    }
  }
  student.fn();  // PandaGuo

上述代码中 console.log(this.name) 写在箭头函数当中,而改箭头函数被 fn 定义的普通函数包含,则箭头函数 this 绑定了 fn 函数指向的 this,也就是 student 对象,故最终输出为 " PandaGuo "

改变普通函数 this 指向的方法:

  1. 使用 ES6 箭头函数;
  2. 函数内部使用 _this = this;
  3. 使用 new 实例化对象;
  4. 使用 apply、call、bind

具体实现方法参考这篇文章:this、apply、call、bind - 掘金 (juejin.cn)

参考文章:

this、apply、call、bind - 掘金 (juejin.cn)

JS 相关面试题第一版 | ChoDocs