您的位置:首页 > Web前端 > JavaScript

javascript运行机制之this详解

2014-02-03 21:08 1151 查看
this是面向对象语言中一个重要的关键字,理解并掌握该关键字的使用对于我们代码的健壮性及优美性至关重要。而javascript的this又有区别于Java、C#等纯面向对象的语言,这使得this更加扑朔迷离,让人迷惑。

this使用到的情况:

1. 纯函数

2. 对象方法调用

3. 使用new调用构造函数

4. 内部函数

5. 使用call / apply 

6.事件绑定

本文地址:http://blog.csdn.net/chen_zw/article/details/18910929

1. 纯函数

var name = 'this is window';  //定义window的name属性
function getName(){
console.log(this);    //控制台输出: Window  //this指向的是全局对象--window对象
console.log(this.name);  //控制台输出: this is window  /
}

getName();
运行结果分析:纯函数中的this均指向了全局对象,即window。

2. 对象方法调用

var name = 'this is window';  //定义window的name属性,看this.name是否会调用到
var testObj = {
name:'this is testObj',
getName:function(){
console.log(this);  //控制台输出:testObj   //this指向的是testObj对象
console.log(this.name);  //控制台输出: this is testObj
}
}

testObj.getName();
运行结果分析:被调用方法中this均指向了调用该方法的对象。

3.  使用new调用构造函数

function getObj(){
console.log(this);    //控制台输出: getObj{}  //this指向的新创建的getObj对象
}

new getObj();
运行结果分析:new 构造函数中的this指向新生成的对象。

4. 内部函数

var name = "this is window";  //定义window的name属性,看this.name是否会调用到
var testObj = {
name : "this is testObj",
getName:function(){
//var self = this;   //临时保存this对象
var handle = function(){
console.log(this);   //控制台输出: Window  //this指向的是全局对象--window对象
console.log(this.name);  //控制台输出: this is window
//console.log(self);  //这样可以获取到的this即指向testObj对象
}
handle();
}
}

testObj.getName();
运行结果分析:内部函数也是函数,所以不出意料的,它的this仍然指向的是全局对象,即window。这里普遍被认为是JavaScript语言的设计错误,因为没有人想让内部函数中的this指向全局对象。一般的处理方式是将this作为变量保存下来,一般约定为that或者self,如上述代码所示。

5. 使用call / apply 

var name = 'this is window';  //定义window的name属性,看this.name是否会调用到
var testObj1 = {
name : 'this is testObj1',
getName:function(){
console.log(this);   //控制台输出: testObj2  //this指向的是testObj2对象
console.log(this.name);  //控制台输出: this is testObj2
}
}

var testObj2 = {
name: 'this is testObj2'
}

testObj1.getName.apply(testObj2);
testObj1.getName.call(testObj2);


Note:apply和call类似,只是两者的第2个参数不同:

[1] call( thisArg [,arg1,arg2,… ] );  // 第2个参数使用参数列表:arg1,arg2,...  

[2] apply(thisArg [,argArray] );     //第2个参数使用 参数数组:argArray 

运行结果分析:使用call / apply  的函数里面的this指向绑定的对象。

6. 事件绑定

事件方法中的this应该是最容易让人产生疑惑的地方,大部分的出错都源于此。

//页面Element上进行绑定
  <script type="text/javascript">
     function btClick(){
console.log(this);  //控制台输出: Window  //this指向的是全局对象--window对象
}
  </script>
  <body>
    <button id="btn" onclick="btClick();" >点击</button>
  </body>
//js中绑定方式(1)
<body>
<button id="btn">点击</button>
</body>
<script type="text/javascript">
function btClick(){
console.log(this);  //控制台输出:<button id="btn">点击</button>  //this指向的是Element按钮对象
}

document.getElementById("btn").onclick = btClick;
document.getElementById("btn").onclick;
</script>
//js中绑定方式(2)
<body>
<button id="btn">点击</button>
</body>
<script type="text/javascript">
document.getElementById("btn").onclick = function(){
console.log(this);  //控制台输出:<button id="btn">点击</button>  //this指向的是Element按钮对象
}
document.getElementById("btn").onclick;
</script>
//js中绑定方式(3)
<body>
<button id="btn">点击</button>
</body>
<script type="text/javascript">
function btClick(){
console.log(this);
}

document.getElementById("btn").addEventListener('click',btClick); //控制台输出:<button id="btn">点击</button>  //this指向的是Element按钮对象把函数(方法)用在事件处理的时候。
document.getElementById("btn").attachEvent('onclick',btClick);  //IE使用,控制台输出: Window  //this指向的是全局对象--window对象,这应该是IE的一个BUG
</script>

运行结果分析:以上2种常用事件绑定方法,在页面Element上的进行事件绑定(onclick="btClick();"),this指向的是全局对象;而在js中进行绑定,除了attachEvent绑定的事件方法外,this指向的是绑定事件的Elment元素。

我们可以使用以下代码修改attachEvent的this指向:

<script type="text/javascript">
//解决attachEvent方法中this的指向
var Event = {};
Event.addEvent = function(target,eventType,handle){
<span style="white-space:pre">	</span>if(document.addEventListener){
target.addEventListener(eventType,handle,false);
}else if(document.attachEvent){
<span style="white-space:pre">		</span>target.attachEvent('on'+eventType,function(){
<span style="white-space:pre">			</span>//这里改变this的指向
<span style="white-space:pre">			</span> handle.apply(target,arguments);
<span style="white-space:pre">		</span>});
<span style="white-space:pre">	</span>}else{
<span style="white-space:pre">	</span>target['on'+eventType] = handle;
<span style="white-space:pre">	</span> }
};
</script>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息