一、关于this的使用
javaScript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境
二、具体到实际应用中,this指向大致可以分为以下4种:
1、作为对象的方法调用
2、作为普通函数调用
3、构造器调用
4、Function.prototype.call和Function.prototype.apply调用
三、闭包中使用this对象会导致的一些问题
this对象是在运行时基于函数的执行环境绑定的,
1、在全局环境中,this 等于 window
2、当函数被作为某个对象的方法调用时,this 等于 (那个对象)
3、匿名函数的执行环境具有全局性,因此其this对象通常指向window
1 //1作为对象的方法调用 2 //当函数作为对象的方法被调用时,this指向该对象 3 var obj = { 4 a:1, 5 getA:function(){ 6 console.log(this); // 输出 Object 7 console.log(this.a); //输出 1 8 } 9 }; 10 obj.getA(); 11 12 13 //2.作为普通函数调用 14 //当函数不作为对象的属性被调用时,此时的this总是指向全局对象。在javaScript中这个全局对象是window对象 15 window.name = "globalName"; 16 var getName1 = function (){ 17 return this.name; 18 }; 19 console.log(getName1()); // 输出 globalName 20 21 //有时候我们会遇到一些困扰,比如在div节点的事件函数内部, 22 //有一个局部的callback方法,callback被作为普通函数的调用时, 23 //callback内部的this指向了window,但我们往往是想让它指向该div节点 24 25 26 window.id = "windowId"; 27 document.getElementById("div1").onclick = function (){ 28 console.log(this.id);//div1 29 var callback = function(){ 30 console.log(this.id);//输出windowId,指向全局window对象----??? 31 }; 32 callback();// 自执行函数中的this指向window 33 }; 34 35 36 //一种简单的解决方案,用一个变量保存div节点的引用 37 window.id = 'windowId'; 38 document.getElementById("div1").onclick = function(){ 39 var that = this; //保存div的引用 40 var callback = function(){ 41 console.log(that.id); // 输出div1 42 }; 43 callback(); 44 }; 45 46 /*ES5下的严格模式下,这种情况下的this已经被规定为不会指向全局对象,而是undefined*/ 47 function func(){ 48 "use strict"; 49 console.log(this);//注意为undefined 50 } 51 func(); 52 53 54 55 //3.构造器的调用 56 //当用new操作符调用函数时,该函数总会返回一个对象,通常情况下,构造器里的this指向返回的那个对象 57 58 var MyClass = function (){ 59 this.name = "six"; 60 }; 61 62 var obj = new MyClass();//大部分js函数都可以当做构造器使用 63 64 console.log(obj.name);//six 65 66 /* 67 * 注意:使用new调用构造器时,还要注意一个问题,如果构造器显示的返回了一个object类型的对象, 68 * 此次的运算结果最终会返回这个对象,而不是我们之前期待的this 69 * 70 * */ 71 var MyClass = function(){ 72 this.name = "GoUp"; 73 return {//构造器显示的返回了一个object类型的对象 74 name:"lalala" 75 }; 76 }; 77 78 var obj = new MyClass(); 79 console.log(obj.name);//lalala 80 81 /* 82 * 注意:如果构造器不显示任何类型数据,或者返回一个非对象类型的数据,就不会造成上述问题 83 * 84 * */ 85 var MyClass = function(){ 86 this.name = "GoUp"; 87 return 'kakaka';//返回string类型 88 }; 89 90 var obj = new MyClass(); 91 console.log(obj.name);//GoUp 92 93 94 95 96 //4.用call()和apply()方法可以修改this的指向 97 var obj1 = { 98 name:'seven', 99 getName:function(){ 100 return this.name; 101 } 102 }; 103 var obj2 = { name:'anne'}; 104 console.log(obj1.getName()); // 'seven' 105 console.log(obj1.getName.call(obj2));// 'anne' 106 107 108 109 /* 110 注意:经常遇到问题:丢失this 111 * */ 112 113 var obj = { 114 myName:'seven', 115 getName:function(){ 116 return this.myName; 117 } 118 }; 119 console.log(obj.getName());//seven 120 var getName2 = obj.getName; 121 console.log(getName2);//function (){return this.myName;} 122 console.log(getName2());//undefined 123 /* 当调用obj.getName时,getName方法是作为obj对象的属性被调用的,此时的this指向obj对象,所以obj.getName()输出'seven' 124 当用另外一个变量getName2来引用obj.getName,并且调用getName2时,此时是普通函数调用方式,this指向全局window,所以执行结果是undefined 125 */ 126 127 128 129 //闭包中出现的问题 130 var name = "The Window"; //全局变量 131 var object = { 132 name : "My Object", 133 getNameFunc : function(){ 134 return function(){ // 返回匿名函数 135 return this.name; //this指向全局对象window 136 }; 137 } 138 }; 139 console.log(object.getNameFunc()());//The Window 140 141 142 143 144 145 var name = "The Window"; 146 var object = { 147 name : "My Object", 148 getNameFunc : function(){ 149 var that = this;//把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了 150 return function(){ 151 return that.name; 152 }; 153 } 154 }; 155 console.log(object.getNameFunc()());//My Object!!!