关于this的一点笔记

全局
函数
构造函数


参考

关于作用域绑定的问题,可以参考我回答的这一篇答案


1. 全局

2. 函数

直接调用函数

  • 非严格模式,指向window
  • 严格模式下,this为当前执行环境,默认undefined

对象方法

直接调用一个对象上的方法时,this指向对象自身:

1
2
3
4
5
6
7
8
9
10
11
12
13
var val = 'global';
var obj = {
val: 'obj',
getValWithFunc: function() {
return this.val;
},
getValWithArrowFunc: () => {
return this.val;
}
}
obj.getValWithFunc(); // 'obj'
obj.getValWithArrowFunc(); // 'global'

如果在对象的函数方法中继续调用函数,该函数的上下文关系将指向全局而非该函数

get set 方法

指向类或者对象自身

原型链上的this

prototype上的this在实例化后指向对象自身

1
2
3
4
5
6
7
8
9
10
function Func() {}
Func.prototype.foo = 'foo';
Func.prototype.getFoo = function() {
console.log(this.foo);
console.log(Func.prototype.foo);
}
const func = new Func();
func.foo = 'bar';
func.getFoo(); // bar, foo

箭头函数

箭头函数始终指向最外层的调用对象的上下文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var val = 'global';
var foo = {
val: 'foo',
bar: {
val: 'bar',
getVal: function() {
return this.val;
},
getValInArrow: () => {
return this.val;
}
}
}
foo.bar.getVal(); // 'bar'
foo.bar.getValInArrow(); // 'global'

3. 构造函数

使用new时,将会创建一个新的上下文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
// 也可以使用class
const val = 'global';
class Func {
constructor() {
this.val = 'Func';
this.foo = {
val: 'foo',
getVal: function() {
console.log(this.val);
},
bar: {
val: 'bar',
getVal: function() {
console.log(this.val);
},
getValInArrow: () => {
console.log(this.val);
}
}
}
}
getVal() {
console.log(this.val);
}
}
var func = new Func();
func.getVal(); // 'Func'
func.foo.getVal(); // 'foo'
func.foo.bar.getVal(); // 'bar'
func.foo.bar.getValInArrow(); // 'Func'

4. DOM

  • html中内联的事件,this指向当前DOM节点
  • 事件处理函数中,一般来说this指向e.target

改变作用域的几种方法

  • 使用var _this = this传入当前的作用域
  • 使用apply或者call绑定当前作用域(会立即执行)
  • 使用bind绑定当前作用域(返回以新的函数,不立即执行)
  • 使用箭头函数,始终指向当前执行环境的最外层
  • 使用::(ES7)指定当前作用域