分4种:
- 作为对象的方法调用
- 作为普通函数调用
- 构造器调用
- Function.prototype.call或Function.prototype.apply调用
1、作为对象的方法调用
当函数作为对象的方法被调用时,this 指向该对象:
var obj = {
a: 1,
getA: function(){
alert ( this === obj ); // 输出:true
alert ( this.a ); // 输出: 1
}
};
obj.getA();
2、作为普通函数调用
当函数不作为对象的属性被调用时,也就是我们常说的普通函数方式,此时的 this 总是指 向全局对象。在浏览器的 JavaScript 里,这个全局对象是 window 对象。
window.name = 'globalName';
var myObject2 = {
name: 'sven',
getName: function(){
return this.name;
}
};
var getName = myObject2.getName;
console.log( getName() ); // globalName 不作为对象的属性,则this指向全局对象window
console.log(myObject2.getName()) // sven 作为对象的属性被调用时,则this指向对象
有时候我们会遇到一些困扰,比如在 div 节点的事件函数内部,有一个局部的 callback 方法, callback 被作为普通函数调用时,callback 内部的 this 指向了 window,但我们往往是想让它指向 该 div 节点,见如下代码:
<html>
<body>
<div id="div1">我是一个 div</div>
</body>
<script>
window.id = 'window';
document.getElementById( 'div1' ).onclick = function(){
alert ( this.id ); // 输出:'div1'
var callback = function(){
alert ( this.id ); // 输出:'window'
}
callback();
};
</script>
</html>
此时有一种简单的解决方案,可以用一个变量保存 div 节点的引用:
document.getElementById( 'div1' ).onclick = function(){
var that = this; // 保存 div 的引用
var callback = function(){
alert ( that.id ); // 输出:'div1'
}
callback();
};
在 ECMAScript 5 的 strict 模式下,这种情况下的 this 已经被规定为不会指向全局对象,而
是 undefined:
function func(){
"use strict"
alert ( this ); // 输出:undefined
}
func();
3、构造器调用
Es5之前没有类,但可以从构造器中创建对象,同时提供了new运算符,看起来像类。在构造器中this指向返回的这个对象。
var MyClass = function(){
this.name = 'sven';
};
var obj = new MyClass();
alert ( obj.name ); // 输出:sven 因为this指向Obj这个返回的对象
但用 new 调用构造器时,还要注意一个问题,如果构造器显式地返回了一个 object 类型的对 象,那么此次运算结果最终会返回这个对象,而不是我们之前期待的 this:
var MyClass = function(){
this.name = 'sven';
return { // 显式地返回一个对象
name: 'anne'
}
};
var obj = new MyClass();
alert ( obj.name ); // 输出:anne
如果构造器不显式地返回任何数据,或者是返回一个非对象类型的数据,就不会造成上述 问题:
var MyClass = function(){
this.name = 'sven'
return 'anne'; // 返回 string 类型
};
var obj = new MyClass();
alert ( obj.name ); // 输出:sven
4、Function.prototype.call或Function.prototype.apply调用
跟普通的函数调用相比,用 Function.prototype.call 或 Function.prototype.apply 可以动态地 改变传入函数的 this:
var obj1 = {
name: 'sven',
getName: function(){
return this.name;
}
};
var obj2 = {
name: 'anne'
};
console.log( obj1.getName() ); // 输出: sven
console.log( obj1.getName.call( obj2 ) ); // 输出:anne
补充:this与call、apply
1、call和apply的区别:传参个数不同
call(指定函数体内this对象的指向,参数1,参数2...)
apply(指定函数体内this对象的指向,参数数组[xx,xx,xx...])
apply更高的使用频率。
2、call和apply的用途:改变this指向
假如该事件函数中有一个内部函数 func,在事件内部调用 func 函数时,func 函数体内的 this 就指向了 window,而不是我们预期的 div,见如下代码:
document.getElementById( 'div1' ).onclick = function(){
alert( this.id ); // 输出:div1
var func = function(){
alert ( this.id ); // 输出:undefined
}
func();
};
这时候我们用 call 来修正 func 函数内的 this,使其依然指向 div:
document.getElementById( 'div1' ).onclick = function(){
var func = function(){
alert ( this.id ); // 输出:div1
}
func.call( this ); // 则会把当前div1传进去作为this的指向
};