JavaScript | 五步弄懂this指向

112 阅读3分钟

JavaScript中的this指向是初学者常常难弄懂的知识点,也常常作为考察点出现在前端面试题、笔试题中。这里和大家一起弄懂this,如有错误,欢迎指出。

首先我们要知道的是,this是函数内部存在的特殊对象,在大部分情况下,函数运行的方式决定了this绑定的值(运行时),可以分为以下五种:

  1. 作为普通函数执行。
  2. 作为对象方法执行。
  3. 作为构造函数执行。
  4. 通过callapplybind绑定this的方法执行。
  5. 作为箭头函数执行。

作为普通函数执行

我们来看下面的代码

var a = 1

function fn() {
    console.log(this.a)
}

fn()

这里的fn没有被任何对象调用,只是作为普通函数在全局作用域下执行,因此this指向全局作用域window(在浏览器中运行),而在全局作用域中通过var关键字声明的变量会被挂载到全局作用域中,所以执行fn输出1

注意:通过letconst声明的变量不会被挂载到全局作用域当中


作为对象方法执行

当对象调用方法时,this便指向对象本身:

const obj = {
    a: 2,
    sayA(): {
        console.log(this.a)
    }
}

obj.sayA()

这里的sayA作为obj对象的方法被调用了,因此函数sayAthis指向obj对象,而obj恰好有个变量为a,所以这里执行obj.sayA输出2


作为构造函数执行

看过红宝书的帅哥美女们应该非常熟悉,当使用new关键字来创建一个构造函数的实例时,会执行如下操作:

  1. 在内存中创建一个新的对象。
  2. 这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性
  3. 构造函数内部的this被赋值为这个新对象(即this指向新对象)
  4. 执行构造函数内部的代码(给新对象添加属性)
  5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

由第三步可知,当作为构造函数时执行,this指向新创建的对象,即构造函数的实例。我们来看下面的代码:

function Fn(a) {
    this.a = a
}

const instance = new Fn(3)
console.log(instance.a)

由于instanceFn的实例,所以instance.a的值就是this.a,因此这里输出3


通过callapplybind绑定this的方法执行

Function的原型方法中,callapplybind这三个方法都能显式地修改this的指向,它们接收的第一个参数即修改后this指向的对象。我们来看下面的代码:

var a = 1

function fn() {
    console.log(this.a)
}

const obj = {
    this.a = 2
}

fn.call(obj)
fn.apply(obj)
fn.bind(obj)()

上面fn分别被callapplybind三个方法修改了this的指向并执行了三次,因为this指向obj所以输出为2 2 2


作为箭头函数执行

ES6新加入了箭头函数,在箭头函数中,this引用的是定义箭头函数的上下文,即在箭头函数定义时,this的值就跟着确定下来了,且不会再被改变。我们来看下面的代码:

var a = 1

const obj = {
    a: 2
}

const sayA = () => {
    console.log(this.a)
}

sayA()
sayA.call(obj)

sayA是在全局作用域中定义的,所以this指向全局作用域,执行sayA输出1,又因为箭头函数的this的值不会被改变,所以sayA.call(obj)企图将sayAthis指向修改为obj的操作是无效的,执行后仍然输出1


看到了这里的朋友是不是觉得this指向也不过如此?相比HTTP的几十种状态码,5种类型对咱们来说简直就是手到擒来。最后,感谢大家的支持,Thanks♪(・ω・)ノ。