搞明白this指向,走遍天下都不怕(一)

778 阅读3分钟

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

JavaScript中的this一直是面试中的热点问题,同时也是JavaScript中的一个难点问题,在JavaScript中this的指向十分灵活,使用场景也很多,所以对于this的熟练掌握是我们前端工程师的一个基本技能之一。今天我们来通过7个实例来讲解this在一些场景中的指向问题,大家也可以先看代码,自己先思考答案,再看自己的答案是否是正确的。

有一种民间流传的说法:“谁调用它,this就指向谁”,这句话其实并不全面,我们还要根据实际情况进行逐个分析。

我想一篇文章里放太多的题目实例也不好,像做考试题似的,所以我会分多篇文章去发布this指向的内容。

全局环境中的this

基础版本

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

function fn2 () {
  'use strict'
  console.log(this)
}

fn1() //?
fn2() //?

这种情况还算简单,因为函数在全局环境中被调用,在非严格模式下this指向window,在严格模式下指向undefined。所以这道题的答案是windowundefined

升级版本

const obj = {
  abc: 10,
  fn: function() {
    console.log(this)
    console.log(this.abc)
  }
}

let fn1 = obj.fn
fn1() // ?

这里的this仍然指向window,因为fn函数虽然是作为对象的一个方法,但是在赋值给fn1之后,fn1仍然是在全局环境中执行的,所以这道题的答案是windowundefined

如果是这样呢?

const obj = {
  a: 10,
  fn: function() {
    console.log(this)
    console.log(this.a)
  }
}

obj.fn() // ?

这就是我们常规的使用方式了,this指向的是调用它的对象,也就是obj对象,所以会输出下面的内容

{a: 10, fn: ƒ}
10

这里要记住,如果函数是被上一级对象调用那么this就指向上一级这个对象,否则就指向全局环境。

对象调用中的this

基础版本

根据上面所讲,再遇到这样的题目时,就要融会贯通。

const user = {
  name: 'shuai',
  fn: function() {
    return this
  }
}

console.log(user.fn() === user) // ?

函数被user对象所调用,所以this指向为user对象,所以这道题答案为true

复杂调用版本

const user = {
  name: 'shuai',
  friend: {
    name: 'guan',
    fn: function() {
        return this.name
    }
  }
}

console.log(user.friend.fn()) // ?

摸清套路之后,再复杂的调用关系也不怕,根据上面所说“函数式被上一级对象调用那么this就指向上一级这个对象”,所以这道题的答案是输出guan

更高阶版本

const u1 = {
  name: 'u1',
  fn: function() {
    return this.name
  }
}

const u2 = {
  name: 'u2',
  fn: function() {
    return u1.fn()
  }
}

const u3 = {
  name: 'u3',
  fn: function() {
    let fn = u1.fn
    return fn()
  }
}

console.log(u1.fn()) // ?
console.log(u2.fn()) // ?
console.log(u3.fn()) // ?
  • 首先来说第一个u1.fn(),这个比较简单,和上面一样,答案为输出u1

  • 第二个相对来讲也还可以,因为u1.fn()返回的就是u1,所以u2.fn()返回的也就是u1

  • 第三个u3.fn()相对就很难了,因为它把u1.fn赋值给了fn,然后直接调用的fn函数。所以这里的this指向是window,所以答案是输出undefined

所以这个公式一定要背下来,不然就会发懵。

这里要记住,如果函数是被上一级对象调用那么this就指向上一级这个对象,否则就指向全局环境。

变种版本

const u1 = {
  name: 'u1',
  fn: function() {
    return this.name
  }
}

const u2 = {
  name: 'u2',
  fn: u1.fn
}

console.log(u2.fn()) // ?

这道题,首先是把u1.fn赋值给u2.fn,然后调用了u2.fn(),因为调用fn的是u2对象,所以this指向的就是u2对象,所以输出的将是u2

今天规律总结

  • 在函数中,严格模式this会被绑定到undefined上,非严格模式会被绑定到window全局对象
  • 通过上下文对象调用函数时,函数内的this会被绑定到该对象上

欢迎我的公众号【小帅的编程笔记】,让自己和他人都能有所收获!