this setTimeout setInterval
1. this与setTimeout setInterval问题
今天遇到了这样一个问题,下面有相关源码解析,相关代码在最底下。在setInterval中使用this出现了问题。当间隔时间到达的时候,auto.apply(this);会自动运行,这个时候,this,呵呵,初学者,包括我当初也认为是当前的一个实例。其实,当一运行,就发现一切不是这样了。clear()与auto()方法中,都引用了当前对象的属性,所以,当运行到这些行,this.xxx(如:this.time) 的值都是undefined了,这个可以通过firebug来调试观察到。
实际上,这个查看了相关资料(不好意思,我不记得在哪查的呢,呵呵),结合自己上面调试观察,是这样的。
setTimeout 或 setInterval 的function 中调用其他方法(例如clear与auto) 运行,在调用之时,这些方法会依附上window对象,相当于是window一个属性,所以这些方法里面的 this代表就是window对象。
下面图是在Chrome 的调试工具下截取的 :

实际上,我再进行了一次测试,证明了setTimeout 或 setInterval 中 被调用的方法(例如上图的k),依附了window,形成了一个闭包。
测试方法:先让变量 i 在六秒自加两次,在第七秒,显示一下 变量 i 的当前值 ,结果是 3 。
下面图是在Chrome 的调试工具下截取的 :

2. this 与 setTimeout setInterval,被调的是原型方法
即使是原型自身的方法,this也不是指向当前对象,而是window对象。
下面图是在Chrome 的调试工具下截取的 :

3. this与setTimeout setInterval问题,这种解决方式
这种方式的解决方式,就是定义的方法里面 把this 赋值给一个变量,利用变量来传当前对象。
例如:下面的var self = this
autoScroll : function(second){
var self = this;
second = second ? second*1000 : 5000;
setInterval(function(){
auto.apply(self);
},second);
}
其实,这种用法很多,Jquery、Prototype等库中,都有用到,只是平时没注意观察罢了。
4. 最下面的组件,还有一点不得不提及的,虽然与主题不同的----apply方法调用
就是对于apply方法的运用,以前不理解,确实不太理解,干嘛不直接调用,象这种形式:obj.foo(),但是现在能体会到一点点强大之处了。
象clear()、auto(),我都是作为私有方法的,但是里面又不得不调用私有变量,如:this.num,所以只能在运行时,当前对象把clear()、auto()拉
进来调用,但clear()、auto()里面又要用上当前对象的私有变量,这样就必须用上apply方法。
我一直想创建自己的博客,今天做了第一次,呵呵。
1 其实,这组件还很不足,还需要进一步优化扩展,版本还是1.0的。
2 /*
3 #wrapper_sp{height:222px;width: 170px;position:relative;z-index:1;clear:both;margin:4px 0 0 0;}
4 #wrapper_sp .bound{height:225px;width: 170px;}
5 #wrapper_sp .scroll_s{position:absolute;height:20px;width: 170px;display:block;bottom:0;left:0;z-index:2;}
6 #wrapper_sp .bound a{height:225px;width: 170px;display: block;}
7 #wrapper_sp .bound a img{height:225px;width: 170px;border:0;}
8 #wrapper_sp .cpages{height:15px;float: right;margin:1px 0 0 5px;}
9 #wrapper_sp .cpages a.shover{background: #ff0;color:#FF0101;filter:alpha(opacity=80);-moz-opacity:0.8;-khtml-opacity: 0.8;opacity:0.8;}
10 #wrapper_sp .cpages a{float:left;height:14px;width:15px;background: #000;border:1px solid #ccc;margin:0 5px 0 0;color:#FFF; text-align:center; text-decoration:none;filter:alpha(opacity=50);-moz-opacity:0.5;-khtml-opacity: 0.5;opacity:0.5;}
11 */
12 /**
13 * @function 单个图片轮换效果
14 * @version 1.0
15 * @author zhangwang
16 * @note 程序入口 m_scroll_pic.init(images,links,second,num,initImg,initLink);
17 */
18
19 var m_scroll_pic = (function(){
20 var parentN = null;//img节点
21 var linkN = null;//整个容器
22 /**
23 * @author zhangwang
24 * @function 清楚前一个节点的样式
25 * @version 1.0
26 */
27 function clear(){
28 var elem = document.getElementById('bhover_0' + this.pre);
29 elem.className = '';
30 }
31 /**
32 * @author zhangwang
33 * @function 设置轮换节点样式以及图片节点的链接
34 * @version 1.0
35 */
36 function auto(){
37 clear.apply(this);
38 this.pre = this.time;
39 linkN.setAttribute('src',this.arr[this.time - 1]);
40 parentN.setAttribute('href',this.arrLinks[this.time - 1]);
41 elem = document.getElementById('bhover_0' + this.time++);
42 elem.className = 'shover';
43 if(this.time > this.num){
44 this.time = 1;
45 }
46 }
47 /**
48 * @author zhangwang
49 * @function 图片滚动的构造函数
50 * @version 1.0
51 */
52 function m_scroll_pic(){//构造函数
53 this.num = 4;//总图片个数
54 this.time = 1;//当前在数组linkN第几个数值
55 this.pre = 1;//保留当前第几个数值的记录
56 this.arr = [];//图片地址
57 this.arrLinks = [];//图片链接
58 }
59 /**
60 * @author zhangwang
61 * @function 图片滚动的原型
62 * @version 1.0
63 */
64 m_scroll_pic.prototype = {
65 /**
66 * @author zhangwang
67 * @function 设置轮转时间
68 * @param second 轮转间隔时间
69 * @version 1.0
70 */
71 autoScroll : function(second){
72 var self = this;
73 second = second ? second*1000 : 5000;
74 setInterval(function(){
75 auto.apply(self);
76 },second);
77 },
78 /**
79 * @author zhangwang
80 * @function 每次轮转更换图片以及点击图片链接和右下角
81 * @param j 当前轮转图片的记录数
82 * @version 1.0
83 */
84 changeImage : function(j){
85 self = this;
86 clear.apply(self);
87 this.time = j;
88 this.pre = this.time;
89 linkN.setAttribute('src',this.arr[this.time - 1]);
90 parentN.setAttribute('href',this.arrLinks[this.time - 1]);
91 elem = document.getElementById('bhover_0' + j);
92 elem.className = 'shover';
93 },
94 /**
95 * @author zhangwang
96 * @function 设置点击图片链接
97 * @param images 图片链接
98 * @version 1.0
99 */
100 setImages:function(images){
101 if(!arguments[0]){throw new Error();}
102 if(typeof images == 'string'){
103 this.arr = images.split(',');
104 }if(Object.prototype.toString.call(images) === '[object Array]'){
105 this.arr = images;
106 }
107 },
108 /**
109 * @author zhangwang
110 * @function 设置点击图片的链接
111 * @param links 链接参数
112 * @version 1.0
113 */
114 setLinks : function(links){
115 if(!arguments[0]){throw new Error();}
116 if(typeof links == 'string'){
117 this.arrLinks = links.split(',');
118 }if(Object.prototype.toString.call(links) === '[object Array]'){
119 this.arrLinks = links;
120 }
121 },
122 /**
123 * @author zhangwang
124 * @function 设置图片总数量
125 * @param num 图片总数量
126 * @version 1.0
127 */
128 setnum : function(num){
129 this.num = num;
130 },
131 /**
132 * @author zhangwang
133 * @function 轮转图片结构
134 * @param num 设置图片数量
135 * @param initImg 默认放的第一张图片
136 * @param length 轮转图片总数
137 * @version 1.0
138 */
139 createTree : function(imgSrc,linkUrl,length){
140 var wrapper = document.getElementById('wrapper_sp');
141 var bound = document.createElement('div');
142 var scroll_s = document.createElement('div');
143 var clear = document.createElement('div');
144 var cpages = document.createElement('span');
145 var a = document.createElement('a');
146 var img = document.createElement('img');
147
148 img.setAttribute('src',imgSrc);
149 img.setAttribute('id','ahover_01');
150 a.setAttribute('href',linkUrl);
151 a.setAttribute('target','_blank');
152 bound.className = 'bound';
153 scroll_s.className = 'scroll_s';
154 cpages.className = 'cpages';
155 clear.style.clear = 'both';
156
157 wrapper.appendChild(scroll_s);
158 wrapper.appendChild(bound);
159 bound.appendChild(a);
160 a.appendChild(img);
161 scroll_s.appendChild(cpages);
162 wrapper.appendChild(clear);
163
164 for(var i = 1;i <= length;i++){
165 var link = document.createElement('a');
166 link.setAttribute('id','bhover_0' + i);
167 link.setAttribute('href','javascript:sp.changeImage(' + i + ')');
168 if(i == 1){
169 link.className = 'shover';
170 }
171 cpages.appendChild(link);
172 link.appendChild(document.createTextNode(i));
173 }
174 parentN = a;
175 linkN = img;
176 },
177 /**
178 * @author zhangwang
179 * @function initializete picture scroll component
180 * @param images picture link
181 * @param links after hit picture link
182 * @param second 每X秒轮换一次图片,参数3,就是3秒
183 * @param num 设置图片数量
184 * @param initImg 默认放的第一张图片
185 * @param initLink 点击默认第一张图片链接地址
186 * @version 1.0
187 */
188 init : function(images,links,second,num,initImg,initLink){
189 if(arguments.length != 6){
190 throw new Error('参数不符合要求,请参考API!');
191 }
192 this.setnum(num);
193 this.createTree(initImg,initLink,this.num);
194 this.setImages(images);
195 this.setLinks(links);
196 this.autoScroll(second);
197 }
198 }
199 m_scroll_pic.prototype.constructor = m_scroll_pic;
200 return {
201 getInstance : function(){
202 return new m_scroll_pic();
203 }
204 }
205 }
206 )();
207

浙公网安备 33010602011771号