1. 全局执行
1). 浏览器:
window
2). node:
global
2. 函数调用
1). 纯粹的全局函数调用
window
2). 严格模式: ‘use strict’
undefined
3.作为对象的方法调用
当一个函数被当作一个对象的方法调用的时候:1
2
3
4
5
6
7
8function test() {
console.log(this.name);
}
var obj = {
name: 'Messi',
foo: test
}
obj.foo();//'Messi'
函数仅仅是一个指针而已,调用的时候上下文仍然算obj的。而如果是直接给一个全局变量:
1 | var name = "Messi"; |
调用的test,而test是一个全局变量,因此this指向全局下的name。
特例
1 | var obj = { |
因为事件机制的问题,setTimeout会稍后执行,然后指向的是window,在定时器内部的匿名函数中以this.foo为参数,但是与obj是没有关系的,指向window,最终只会输出123,不会执行定时器的函数。可以将setTimeout外的this对象存起来之后,传递给里面的函数,而这就需要闭包的特性来解决。1
2
3
4
5
6
7
8foo2: 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 ;
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
10function 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”确实生效了。