
[Javascipt]关于this关键字在setTimeout和setInterval中的使用问题 |
经过一天的探索和研究,终于有了一些结果。事件起因是这样的......本来我打算用Javascript做一个通用的滚动条类,这样页面出现任何种滚动都只要新建一个实例就可以了,本来是非常顺利的,不过中间却出现了一个小插曲。 JavaScript代码
其中objid为要滚动的容器ID,step为每一轮滚动的距离,direct为滚动方向。基础结构和一些方法就不去管了,直接进入关键点。 roll类的主要方法(都通过prototype设置)有: initroll(); //初始化滚动 可以看出,我的设想是,创建滚动版只需要: JavaScript代码
这里已经在创建实例的时候初始化了,为什么还要initroll呢?因为我想,滚动动作并不是加载后立即执行的,而是在设定的几秒时间后,所以在initroll()中的最重要的内容便是: JavaScript代码
有经验的人可能看出了这里的问题,可是我却一点都没有发觉,这里记录一下问题一。 playroll(),stoproll()都只是开关来控制rollPlaying(),他们的内容分别是: JavaScript代码
JavaScript代码
这里playroll()出了和上面一样的问题记录问题二。 rollPlaying()中的滚动处理本身并没有什么问题,但是因为上面出现的错误而导致了运行出错。那么问题在哪里呢? 问题一:setTimeout(func, time)里面的func我使用了this关键字,来标识是类实例的方法,至少我个人一直认为是这样的,func参数中使用this关键字本身并没有问题, 可以正确在time时间后执行playroll(),可是在playroll()里面就碰到了问题二。(可能有人会说,你的setTimeout的func参数没有带括号,实事证明有括号的情况比没有更惨烈。。。) 问题二:可见我在playroll()中使用了大量的this关键字来标识roll类实例的元素或方法,但是因为问题一是在setTimeout中使用playroll()这个方法,因此这里的this已经不是我设想的类实例的this关键字了。我至今还没有弄明白在前面的setTimeout中使用this关键字的方法导致了playroll中的this变成了什么,总而言之这个this已经不是roll的一个实例了。前面也说playroll()中的错误和initroll()中的错误一样,同样导致了rollPlaying()中的this关键字失效。 解决问题的方法应该有两个:其一是不使用this关键字而用其他的方式替代(因为我觉得太麻烦而且会破坏结构于是放弃了);其二是我现在用的解决方案,如下: JavaScript代码
JavaScript代码
我在initroll()中创建了一个变量o为this本身,再使用匿名方法把o作为实例本身,也作为参数传递给了playroll(),为什么要既作为实例本身又作为参数呢?作为实例的作用是可以在playroll()中使用this关键字,而作为参数是为了在playroll()当中不用再为setInterval重新申明一个实例。 有人可能会说,为什么不setTimeout(function(){this.playroll()}, this.iResume)呢?这样显然不行的原因连试都不用试了,因为这样的情况下匿名方法内的this关键字变成了匿名方法本身而不是外部类,所以才需要一个变量来处理,或者可以看作一个闭包,在initroll结束之后o变量的作用域仍然存在。 为了这个问题绕了一些弯路,觉得应该记录一下,以备后患 |