【转】javascript运行机制之this详解
this是面向对象语言中一个重要的关键字,理解并掌握该关键字的使用对于我们代码的健壮性及优美性至关重要。而javascript的this又有区别于Java、C#等纯面向对象的语言,这使得this更加扑朔迷离,让人迷惑。
this使用到的情况:
1. 纯函数
2. 对象方法调用
3. 使用new调用构造函数
4. 内部函数
5. 使用call / apply
6.事件绑定
---------------------------------------------------------------
1. 纯函数
1 var name = 'this is window'; //定义window的name属性 2 function getName(){ 3 console.log(this); //控制台输出: Window //this指向的是全局对象--window对象 4 console.log(this.name); //控制台输出: this is window / 5 } 6 7 getName();
运行结果分析:纯函数中的this均指向了全局对象,即window。
2. 对象方法调用
1 var name = 'this is window'; //定义window的name属性,看this.name是否会调用到 2 var testObj = { 3 name:'this is testObj', 4 getName:function(){ 5 console.log(this); //控制台输出:testObj //this指向的是testObj对象 6 console.log(this.name); //控制台输出: this is testObj 7 } 8 } 9 10 testObj.getName();
运行结果分析:被调用方法中this均指向了调用该方法的对象。
3. 使用new调用构造函数
1 function getObj(){ 2 console.log(this); //控制台输出: getObj{} //this指向的新创建的getObj对象 3 } 4 5 new getObj();
运行结果分析:new 构造函数中的this指向新生成的对象。
4. 内部函数
1 var name = "this is window"; //定义window的name属性,看this.name是否会调用到 2 var testObj = { 3 name : "this is testObj", 4 getName:function(){ 5 //var self = this; //临时保存this对象 6 var handle = function(){ 7 console.log(this); //控制台输出: Window //this指向的是全局对象--window对象 8 console.log(this.name); //控制台输出: this is window 9 //console.log(self); //这样可以获取到的this即指向testObj对象 10 } 11 handle(); 12 } 13 } 14 15 testObj.getName();
运行结果分析:内部函数中的this仍然指向的是全局对象,即window。这里普遍被认为是JavaScript语言的设计错误,因为没有人想让内部函数中的this指向全局对象。一般的处理方式是将this作为变量保存下来,一般约定为that或者self,如上述代码所示。
5. 使用call / apply
1 var name = 'this is window'; //定义window的name属性,看this.name是否会调用到 2 var testObj1 = { 3 name : 'this is testObj1', 4 getName:function(){ 5 console.log(this); //控制台输出: testObj2 //this指向的是testObj2对象 6 console.log(this.name); //控制台输出: this is testObj2 7 } 8 } 9 10 var testObj2 = { 11 name: 'this is testObj2' 12 } 13 14 testObj1.getName.apply(testObj2); 15 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应该是最容易让人产生疑惑的地方,大部分的出错都源于此。
1 //页面Element上进行绑定 2 <script type="text/javascript"> 3 function btClick(){ 4 <span style="white-space:pre"> </span>console.log(this); //控制台输出: Window //this指向的是全局对象--window对象 5 <span style="white-space:pre"> </span> } 6 </script> 7 <body> 8 <button id="btn" onclick="btClick();" >点击</button> 9 </body>
1 //js中绑定方式(1) 2 <body> 3 <button id="btn">点击</button> 4 </body> 5 <script type="text/javascript"> 6 function btClick(){ 7 console.log(this); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象 8 } 9 10 document.getElementById("btn").onclick = btClick; 11 document.getElementById("btn").onclick; 12 </script>
1 //js中绑定方式(2) 2 <body> 3 <button id="btn">点击</button> 4 </body> 5 <script type="text/javascript"> 6 document.getElementById("btn").onclick = function(){ 7 console.log(this); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象 8 } 9 document.getElementById("btn").onclick; 10 </script>
1 //js中绑定方式(3) 2 <body> 3 <button id="btn">点击</button> 4 </body> 5 <script type="text/javascript"> 6 function btClick(){ 7 console.log(this); 8 } 9 10 document.getElementById("btn").addEventListener('click',btClick); //控制台输出:<button id="btn">点击</button> //this指向的是Element按钮对象把函数(方法)用在事件处理的时候。 11 document.getElementById("btn").attachEvent('onclick',btClick); //IE使用,<span style="font-family: Arial, Helvetica, sans-serif;">控制台输出: Window //this指向的是全局对象--window对象</span> 12 13 </script>
运行结果分析:以上2种常用事件绑定方法,在页面Element上的进行事件绑定(onclick="btClick();"),this指向的是全局对象;而在js中进行绑定,除了attachEvent绑定的事件方法外,this指向的是绑定事件的Elment元素。