js中深入了解this指向

本文最后更新于:2023年8月24日 晚上

普通函数中的this

我们都知道在普通的函数(使用function关键字定义)中,this的指的是它所属的对象

但它拥有不同的值,分以下情况决定:

  1. 在方法中,this指的是所有者对象
  2. 单独的情况下,this指的是全局对象
  3. 在函数中,this指的是全局对象
  4. 在函数中,严格模式("use strict";)下,thisundefined
  5. 在事件中,this指的是接收事件的元素

箭头函数中的this

在es6的箭头函数中的this指向是全局对象(window),也就是说无论在哪个对象中都可以指向全局,但是在es6的类中指向是类的实例对象(因为在类的原型链上)

详细区别(type=”text/javascript”)

使用this作为当前标签的dom对象传递就不展示了

简单使用

1
2
3
4
5
6
7
8
9
10
function demo1() {
console.log('普通函数中的this:', this) // Window对象
}

demo1()

const demo2 = () => {
console.log('箭头函数中的this:', this) // Window对象
}
demo2()

在对象中使用

1
2
3
4
5
6
7
8
9
10
11
const obj = {
name: 'FSAN',
demo1: function () {
console.log('在obj对象普通函数中的this:', this) // obj对象
},
demo2: () => {
console.log('在obj对象箭头函数中的this:', this) // Window对象
}
}
obj.demo1()
obj.demo2()

在类中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class C1 {
name = 'FSAN'
// 简写形式
demo1() {
console.log('类的普通方法中的this:', this) // 类的实例对象
}
demo2 = function () {
console.log('类的普通方法中的this:', this) // 类的实例对象
}
demo3 = () => {
console.log('类的箭头函数中的this:', this) // 类的实例对象
}
}
const c1 = new C1()
c1.demo1()
c2.demo2()
c2.demo3()

可以发现在类中使用哪种方法定义方法对this的指向都没有影响

手动严格模式

1
"use strict";

加上这段之后,会改变简单使用中使用function定义的方法中的this指向

1
2
3
4
function demo1() {
"use strict";
console.log('严格模式下普通函数中的this:', this) // undefined
}

对其他方法没有影响

详细区别(type=“text/babel”)

将js代码通过babel转换,先导入

1
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

简单使用

1
2
3
4
5
6
7
8
9
function demo1() {
console.log('babel编译后:普通函数下的this:', this) // undefined
}

demo1()
const demo2 = () => {
console.log('babel编译后:箭头函数下的this:', this) // undefined
}
demo2()

查看转换后源码,分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
"use strict";

function demo1() {
console.log('babel编译后:普通函数下的this:', this); // undefined
}

demo1();

const demo2 = () => {
console.log('babel编译后:箭头函数下的this:', void 0); // undefined
};

demo2();

转换后,会默认转换为严格模式(对简单定义的普通函数有影响,但是手写严格模式对this没有影响),但是!这里转换后将箭头函数中的this改成了void 0

在对象中使用

1
2
3
4
5
6
7
8
9
10
11
const obj = {
name: 'FSAN',
demo1: function () {
console.log('babel编译后:obj对象普通函数中的this:', this) // obj对象
},
demo2: () => {
console.log('babel编译后:obj对象箭头函数中的this:', this) // undefined
}
}
obj.demo1()
obj.demo2()

在类中使用

由实例对象调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class C1 {
name = 'FSAN'

demo1() {
console.log('babel编译后:类中普通函数的this:', this) // 类的实例对象
}

demo2 = () => {
console.log('babel编译后:类中箭头函数的this:', this) // 类的实例对象
}
}

const c1 = new C1()
c1.demo1()
c1.demo2()

由其他引用地址调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class C1 {
name = 'FSAN'

demo1() {
console.log('babel编译后:类中普通函数的this:', this) // 类的实例对象
}

demo2() {
console.log('babel编译后:类中箭头函数的this:', this) // undefined
}
}

const c1 = new C1()
const demo2 = c1.demo
demo2()

要想让demo2中的this正确指向类的实例对象,只需要让demo2使用箭头函数即可

总结

  1. 在类中构造器的this,一定指向类的实例对象
  2. 类中的方法由实例对象调用,其中的this才是实例对象
  3. 使用babel转换时,默认使用严格模式会将除了类之外的箭头函数中的this转换为void 0(这就是使用babel后,函数中拿到thisundefined的原因)

js中深入了解this指向
https://xin-fas.github.io/2022/07/12/js中this指向/
作者
Xin-FAS
发布于
2022年7月12日
更新于
2023年8月24日
许可协议