一、关于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!!!