今天抽空读了下曾探的《javascript设计模式与开发实践》,看了其中的this这一节,终于让我重新认识了JS里的this
!
javascript中的this总是指向一个对象
,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而不是函数被声明是的环境!
this指向大致分为以下四种:
1. 作为对象的方法调用
2. 作为普通函数调用
3. 构造器作用
4. Function.prototype.call或Function.protyotype.apply调用
1. 作为对象的方法调用
当函数作为对象的方法被调用时,this就指向该对象(这个很好理解):1
2
3
4
5
6
7
8var obj = {
name : 'zhu',
getName : function(){
alert(this.name); //zhu
alert(this === obj); //true
}
}
obj.getName();
2. 作为普通函数调用
就是不作对象的方法被调用,此时this指向全局对象window
1
2
3
4
5
6
7
8
9window.name = '我是全局name';
var myObj = {
name : '我是局部name',
getName : function(){
return this.name;
}
};
var getName = myObj.getName;
console.log( getName() ); //我是全局name
所以必须要看是谁调用了这个函数,此时this就指向谁
注:在ECMAScript5的strict模式下,作为普通函数被调用时,this指向的是
undefined
,而非window!
1
2
3
4 (function fun(){
"use strict"
alert(this); //undefined
})()
3. 构造器作用
在JS中大部分函数都可以被作为构造器使用,当用new来调用函数时,该函数总是会返回一个对象,通常情况下,构造器里的this就指向返回的这个对象。1
2
3
4
5var MyName = function(){
this.name = 'zhu';
};
var obj = new MyName;
alert(obj.name) //zhu
但如果构造器显式的返回一个对象,那么此次运算最终会返回这个对象,而非this:1
2
3
4
5
6
7
8
9var MyName = function(){
this.name = 'zhu';
return {
name : 'wang'
}
};
var obj = new MyName;
console.log( obj.name ); //wang
4. Function.prototype.call或Function.prototype.apply调用:
总的来说就是通过call
或apply
来改变函数中this的指向1
2
3
4
5
6
7
8
9
10
11var obj1 = {
name : 'zhu',
getName : function(){
return this.name;
}
};
var obj2 = {
name : 'wang'
};
console.log( obj1.getName() ); //zhu
console.log( obj1.getName.apply( obj2 )); //wang
5. 此外我们往往会遇到我们期待this指向的是这个对象,而实际它指向的却是另一个我们意料之外的对象。。。1
2
3
4
5
6
7
8
9
10
11window.name = 'wang';
var obj = {
name : 'zhu',
getName : function(){
return this.name;
}
};
console.log( obj.getName() ) //zhu
var obj2 = obj.getName;
console.log( obj2() ) //wang
上面的obj.getName是作为对象的方法来调用的,而后面obj2 = obj.getName
只是把obj的getName函数赋值给obj2,然后obj2被调用,此时它只是一个普通函数,其中的this指向的是window
!
最后我们可以考虑下下面这两段代码:1
2
3
4
5
6
7
8
9
10
11
12
13/*下面一段输出正常*/
document.getElementById = (function(fun){
return function(){
return fun.apply(document,arguments);
}
})(document.getElementById);
var getId = document.getElementById;
var div = getId( 'div1' );
alert( div );
/*下面的会报错*/
var getId = document.getElementById;
alert( getId( 'div1' ) );