JavaScript中的this引用
在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。这个跟第一点的全局函数调用的全局变量一样。
以上总结的情况未必完整,若在工作中发现有其他情况再补充进来。