javascript運行機制之this詳解


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" οnclick="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上的進行事件綁定(οnclick="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>


發佈了109 篇原創文章 · 獲贊 101 · 訪問量 216萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章