浅谈javascript里的this

今天抽空读了下曾探的《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
8
var 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
9
window.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
5
var MyName = function(){
this.name = 'zhu';
};
var obj = new MyName;
alert(obj.name) //zhu

但如果构造器显式的返回一个对象,那么此次运算最终会返回这个对象,而非this:

1
2
3
4
5
6
7
8
9
var MyName = function(){
this.name = 'zhu';
return {
name : 'wang'
}
};

var obj = new MyName;
console.log( obj.name ); //wang

4. Function.prototype.call或Function.prototype.apply调用:
总的来说就是通过callapply来改变函数中this的指向

1
2
3
4
5
6
7
8
9
10
11
var 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
11
window.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' ) );

文章目录