JavaScript中的this

This

1. 全局执行

1). 浏览器:

window

2). node:

global

2. 函数调用

1). 纯粹的全局函数调用

window

2). 严格模式: ‘use strict’

undefined

3.作为对象的方法调用

当一个函数被当作一个对象的方法调用的时候:

1
2
3
4
5
6
7
8
function test() {
console.log(this.name);
}
var obj = {
name: 'Messi',
foo: test
}
obj.foo();//'Messi'

函数仅仅是一个指针而已,调用的时候上下文仍然算obj的。而如果是直接给一个全局变量:

1
2
3
4
5
6
7
8
9
var name = "Messi";
var obj = {
name: 'CR',
foo: function() {
console.log(this.name);
}
}
var test = obj.foo;
test();//"Messi

调用的test,而test是一个全局变量,因此this指向全局下的name。

特例

1
2
3
4
5
6
7
8
9
10
11
var obj = {
name: 'Messi',
foo: function() {
console.log(this);
},
foo2: function() {
console.log(123);
setTimeout(this.foo,1000);
}
}
obj.foo2();

因为事件机制的问题,setTimeout会稍后执行,然后指向的是window,在定时器内部的匿名函数中以this.foo为参数,但是与obj是没有关系的,指向window,最终只会输出123,不会执行定时器的函数。可以将setTimeout外的this对象存起来之后,传递给里面的函数,而这就需要闭包的特性来解决。

1
2
3
4
5
6
7
8
foo2: function() {
console.log(123);
var _this = this;
setTimeout(function(){
console.log(this);//window
console.log(_this);//Object {name: "Messi"}
},1000);
}

隐式绑定this

即使在严格模式下,setTimeout方法在调用传入函数的时候,如果这个函数没有指定了的 this,那么它会做一个隐式的操作,自动地注入全局上下文,等同于调用 foo.apply(window)而非foo();

1
2
3
4
5
'use strict';
function foo() {
console.log(this);
}
setTimeout(foo,1);//window

4. 作为构造函数使用

new操作符干的事,不再赘述,最后this指向的是实例对象

5. 箭头函数(Arrow function)

继承了外围作用域的this对象,并且在词法作用域阶段就已经决定好了,call/apply/bind都无法改变

6. call,apply,bind

说一个特例:在构造函数中如果用bind改变this,并不会生效。

1
2
3
4
5
6
7
8
9
10
function Person(name){
this.name = name;
console.log(this.name);
}
var obj = {
name : "qdedd"
}
var Person2 = Person.bind(obj,"Messi");
var person = new Person2("leo");
console.log(person)//"Messi" person

可以看到,new实例并没有改变指向为obj,this仍然指向的是person。但是传入的参数”Messi”确实生效了。