this 指向问题

JavaScript 中的this指向问题真的是被反反复复的说起,不管是前端新人还是职场老鸟,总会被这个 this 搞的蒙圈,而它又是面试特别喜欢问的问题,所以每次面试前都要复习一下,有点无奈。针对这种情况,我只想说一句“我太难了”。

难.jpg

其实要搞懂 this 指向,就要先搞清楚它的存在场景,主要就是三大场景:

  1. 普通函数中
  2. 箭头函数中
  3. bind,call,apply

普通函数中的 this

普通函数就是非箭头函数,看 this 指向就要看它是怎么被调用的,普通函数有三种调用方式:

  1. 直接调用,如:func()
  2. 对象调用,如:obj.func()
  3. 使用 new,如:new func()

直接调用

对于直接调用的函数,就不用多想了,其内部的 this 都指向的是全局 Window对象

function func() {
  console.log(this.a) 
}
var a = 123
func() // 123

哪怕你的函数在别的函数内部调用,只要是直接调用的,this 都指向Window,比如这样:

function func1() {
  console.log(this.a) 
}
var a = 123

function func2() {
  var a = 456
  func1()
}
func2()  // 123

对象调用

对于对象调用,这样的obj.func(),那 this 指向的就是前面的对象,即obj,此时只需要记住,谁调用了函数,谁就是 this。示例:

function func() {
  console.log(this.a)
}
var a = 123

var obj = {
  a: 456,
  func: func
}

obj.func()  // 456

使用 new 调用

使用 new 调用后,this 被永远绑定在生成的实例上,不会被任何方法改变

function func() {
  console.log(this.a)
}
var a = 123

var n = new func()  // undefined,因为实例 n 上没有 a 属性

箭头函数中的 this

箭头函数中的this,就更让人摸不着头脑了,其实箭头函数里是不存在 this 的,箭头函数中的 this 只取决包裹箭头函数的第一个普通函数的 this,举个例子:

function func() {
  return () => {
    return () => {
      console.log(this)
    }
  }
}
func()()() // Window

例子中,因为包裹箭头函数的第一个普通函数是 func,所以此时的 thisWindow

而且,箭头函数中的 this 值,取决于它定义时所在的对象,而不是使用时所在的对象,怎么理解这个呢,举个例子:

var obj = {
  a: 123,
  func: () => {
    console.log(this.a)
  }
}
var a = 456
obj.func()

我相信很多人都会做错例子中的题,都会觉得打印结果是123,而正确答案应该是456。因为箭头函数中的this值取决于定义时的对象,而不是调用时的对象,这跟普通函数相反的。func定义在对象obj中,此对象不具备作用域,所以this指向全局Window

bind,call,apply

这三个也不用多说,this是第一个参数。这里重点说一下bind,如果对一个函数进行多次 bind,那么最终this指向谁?例子:

var a = { name: 'a' }
var b = { name: 'b' }
function func() {
  console.log(this)
}
func.bind(a).bind(b)()

例子中的输出结果是a而不是b,记住不管我们给函数 bind 几次,func 中的 this 永远由第一次 bind 决定。而applycall因为绑定的同时就执行了函数,所以不支持这种链式绑定。

你可能感兴趣的:(this 指向问题)