在JavaScript的學習當中,this關鍵字的出現頻率可不低,所以想想有必要對this關鍵字做一個總結。在總結過程中,參考的資料來源於書本及網上。 一、定義 1、this是函數內部的一個特殊對象(或this引用)--它引用的是函數據以執行的環境對象。(來源於JavaScript高級程式設計) 2 ...
在JavaScript的學習當中,this關鍵字的出現頻率可不低,所以想想有必要對this關鍵字做一個總結。在總結過程中,參考的資料來源於書本及網上。
一、定義
1、this是函數內部的一個特殊對象(或this引用)--它引用的是函數據以執行的環境對象。(來源於JavaScript高級程式設計)
2、this引用是一種在JavaScript的代碼中隨時都可以使用的只讀變數。 this引用 引用(指向)的是一個對象,它有著會根據代碼上下文語境自動改變其引用對象的特性。它的引用規則如下:
• 在最外層代碼中,this引用 引用的是全局對象。
• 在函數內,this引用根據函數調用的方式的不同而有所不同。如下
1)構造函數的調用--this引用 引用的是所生成的對象
2)方法調用--this引用 引用的是接收方對象
3)apply或call調用--this引用 引用的是有apply或call的參數指定的對象
4)其他方式的調用--this引用 引用的是全局對象
(來源於JavaScript編程全解)
二、根據以上所述及網上的相關資料,this對象(引用)的使用情況總結如下:
JavaScript是動態語言,this關鍵字在執行的時候才能確定是誰。所以this永遠指向調用者,即對“調用對象”的引用。簡單點說就是調用的方法屬於哪個對象,this就指向那個對象。根據函數調用方式的不同,this可以 指向全局對象,當前對象,或其他任意對象。
1、全局函數調用,全局函數中的this會指向全局對象window。(函數調用模式)
1 //代碼清單1 2 <script type="text/javascript"> 3 var message = "this in window"; //這一句寫在函數外面和裡面是一樣效果 4 function func() { 5 if(this == window){ 6 alert("this == window"); 7 alert(message); 8 this.methodA = function() { 9 alert("I'm a function"); 10 } 11 } 12 } 13 14 func(); //如果不調用func方法,則裡面定義的屬性或方法會取不到 15 methodA(); 16 </script>
func()的調用結果為this == window, this in window
methodA()的調用結果為I'm a function
2、構造函數調用,即使用new的方式實例化一個對象,this會指向通過構造函數生成的對象。(構造器調用模式)
1 代碼清單2 2 <script type="text/javascript"> 3 function Func() { 4 if (this == window) { 5 alert("this == window"); 6 } 7 else { 8 alert("this != window"); 9 } 10 this.fieldA = "I'm a field"; 11 alert(this); 12 } 13 14 var obj = new Func(); 15 alert(obj.fieldA); //this指向的是對象obj 16 </script>
3、對象方法的調用,this指向當前對象。任何函數,只要該函數被當做一個對象的方法使用或賦值時,該函數內部的this都是對該對象本身的引用。也可理解為this寫在一個普通對象中,this指向的就是對象本身。(方法調用模式)
(方法的定義: 作為對象屬性的函數稱為方法)
1 //代碼清單3 2 <script type="text/javascript"> 3 var obj = { 4 x: 3, 5 doit: function(){ 6 if(this == window){ 7 alert("this == window"); 8 }else{ 9 alert("method is called: " + this.x); 10 } 11 } 12 }; 13 14 obj.doit(); //this指向的是對象obj 15 </script>
4、通過apply或call方法調用,this指向傳入的對象。
apply 或call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變為由 thisObj 指定的新對象。如果沒有提供 thisObj 參數,那麼 Global 對象被用作 thisObj。 (apply調用模式)
1 //代碼清單4 2 <script type="text/javascript"> 3 var obj = { 4 x: 3, 5 doit: function(){ 6 alert("method is called: " + this.x); 7 } 8 }; 9 var obj2 = {x: 4}; 10 11 obj.doit(); //3,this指向obj 12 obj.doit.apply(obj2); //4,this指向obj2 13 obj.doit.call(obj2); //4,this指向obj2 14 </script>
5、原型鏈中的this --原型對象及構造函數中的this指向新創建的實例對象。使用prototype擴展方法可以使用this獲取到源對象的實例,私有欄位無法通過原型鏈獲取。
1 //代碼清單5 2 <script type="text/javascript"> 3 function Func() { 4 this.fieldA = "I'm a field"; 5 var privateFieldA = "I'm a var"; 6 } 7 8 Func.prototype = { 9 ExtendMethod: function(str) { 10 alert(str + " :" + this.fieldA); 11 alert(privateFieldA); //出錯,私有欄位無法通過原型鏈獲取。 12 } 13 }; 14 15 var obj = new Func(); 16 obj.ExtendMethod("From prototype"); //此時構造函數及原型鏈中的this指向對象obj 17 </script>
6、閉包中的this --閉包:寫在function中的function,this指向全局對象window。
6.1 對象中的閉包
1 //代碼清單6 2 <script type="text/javascript"> 3 var name = "The window"; 4 var obj = { 5 name: "My Object", 6 getNameFunc: function(){ 7 return function(){ 8 return this.name; 9 } 10 } 11 }; 12 13 alert(obj.getNameFunc()()); //The window 14 </script>
此時,閉包中的this指向全局對象window,只能取到全局對象的屬性。那麼對象內部的屬性(外部函數的變數)要想訪問又怎麼辦呢? 把外部函數的this對象保存在一個閉包能訪問的變數就可以了。看如下代碼:
1 //代碼清單7 2 <script type="text/javascript"> 3 var name = "The window"; 4 var obj = { 5 name: "My Object", 6 getNameFunc: function(){ 7 var that = this; 8 return function(){ 9 return that.name; 10 } 11 } 12 }; 13 14 alert(obj.getNameFunc()()); //My object 15 </script>
將外部函數的this賦值給that變數,就能讀取到外部函數的變數。
6.2 不管是直接引用function,還是實例化一個function,其返回的閉包函數里的this都是指向window。
1 //代碼清單8 2 <script type="text/javascript"> 3 function a() { 4 alert(this == window); 5 var that = this; 6 var func = function() { 7 alert(this == window); 8 alert(that); 9 }; 10 return func; 11 } 12 13 var b = a(); 14 b(); //true, true, [object Window] 15 var c = new a(); 16 c(); //false, true, [object object] 17 </script>
7、函數使用bind()方法綁定一個對象,this會指向傳給bind()函數的值。
1 //代碼清單9 2 <script type="text/javascript"> 3 window.color = "red"; 4 var obj = {color: "blue"}; 5 function sayColor(){ 6 alert(this.color); 7 } 8 9 var objSayColor = sayColor.bind(obj); 10 objSayColor(); //blue 11 </script>
8、內嵌在HTML元素中的腳本段,this指向元素本身
1 //代碼清單10 2 <div onclick="test(this)" id="div">Click Me</div> 3 <script type="text/javascript"> 4 function test(obj) { 5 alert(obj); //[object HTMLDivElement] 6 } 7 </script>
9、寫在script標簽中:this就是指全局對象window。這個跟第一點的全局函數調用的全局變數一樣。
以上總結的情況未必完整,若在工作中發現有其他情況再補充進來。