`
cuixiping
  • 浏览: 19919 次
  • 性别: Icon_minigender_1
  • 来自: 地球
社区版块
存档分类
最新评论

setTimeout与setInterval在不同浏览器下的差异研究

阅读更多
setTimeout与setInterval是window对象的两个非常神奇方法,用于实现定时或延时调用一个函数或一段代码。
(新手可能认为setTimeout与setInterval是javascript函数,这是错误的。新手容易将javascript对象函数与DOM对象方法混淆。)

先来一段代码,大家猜猜在各种浏览器下的结果会是怎么样的呢?
function f(){
    var s = 'arguments.length:'+arguments.length+'; ';
    for(var i=0,n=arguments.length;i< n;i++){
        s += ' ['+i+']:'+arguments[i]+'; ';
    }
    alert(s);
}
setTimeout(f,500,"javascript","AAA")


我这里要探讨的,不是什么时候该用哪一个,而是探讨这两个方法在各浏览器中的差异。

原先我一直没觉得这两个方法会有什么乌龙,一个偶然的机会让我得知了,现在整理一下写出来和大家分享。

因为setTimeout与setInterval的参数和用法是一样的,只是功能不同,所以,为了省事,我下面只以setTimeout为例进行说明以及举例。

setTimeout被最经常用到的形式大概是如下2种样子的:
    iTimerID = setTimeout(strJsCode, 50)   //strJsCode为一个包含js代码的字符串
    iTimerID = setTimeout(objFunction, 50) //objFunction为一个函数对象

第一种调用方式是传包含js代码的字符串,这种方式的好处是简洁,但坏处是运行效率差,而且不利于语法解析,有潜在风险,更重要的是,处理比较复杂的内容比较费劲,这一点和eval的弊端是一致的。
所以,我们认为,通常应当采用第二种方式调用为好。(后面我的例子均采用第2种调用方式)


现在来揭晓开头那一段代码在各种浏览器下的结果:
    IE(6,7,8)是: arguments.length:0;
    Opera(6,7,8)是: arguments.length:2;  [0]:javascript;  [1]:AAA;
    Firefox(3.0)是: arguments.length:3;  [0]:javascript;  [1]:AAA;  [2]:-15;
竟然有这么大的差别,还真是“你唱你的曲,我哼我的调”!
Firefox(3.0)下,得出的最后一个数字是不特定的,有时候是0,有时候是一个负数,这问题后面再说。


(一)IE系列中的setTimeout

首先,我们看看微软出的DHTML参考手册中是如何说的:

setTimeout Method
    Evaluates an expression after a specified number of milliseconds has elapsed.

Syntax
    iTimerID = window.setTimeout(vCode, iMilliSeconds [, sLanguage])

Parameters
    vCode           Required. Variant that specifies the function pointer or string that indicates
                    the code to be executed when the specified interval has elapsed.
    iMilliSeconds   Required. Integer that specifies the number of milliseconds.
    sLanguage       Optional. String that specifies one of the following values:
                        JScript Language is JScript.
                        VBScript Language is VBScript.
                        JavaScript Language is JavaScript.

MSDN上关于setTimeout的说明:
        http://msdn.microsoft.com/en-us/library/ms536753(VS.85).aspx

也就是说,setTimeout接收3个参数,第3个参数表示脚本语言的类型,如果你再传入更多的参数,是无意义的。
因此,在IE中,以下两种都是对的。
       
setTimeout('alert(1)', 50)

       
setTimeout('msgbox "终止、重试、忽略,您看着办吧。", vbAbortRetryIgnore + vbDefaultButton2, "告诉您"', 50, 'VBScript')



(二)Mozilla系列中的setTimeout

我们看看Mozilla官方网站上 Gecko DOM Reference 手册中是如何说的:
window.setTimeout
    Summary
        Executes a code snippet or a function after specified delay.

    Syntax
        var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
        var timeoutID = window.setTimeout(code, delay);
前两个参数都一样,没差别,从第三个参数就不同了。
因为目前只有IE浏览器支持多种语言的脚本,其它浏览器只支持js脚本所以不需要传语言类型的参数。
Mozilla把传给setTimeout的第3个以及更后面的更多参数依次的传给前面的func做为参数。
Firefox, Opera, Safari, Chrome等等也都是如此。

但是注意到,Mozilla上说了他家的setTimeout有一个叫做"Lateness" argument的BUG.
        "Lateness" argument
                Functions invoked by setTimeout are passed an extra "lateness" argument in Mozilla,
                i.e., the lateness of the timeout in milliseconds. (See bug 10637 and bug 394769.)
这就是开头那个例子中,Firefox(3.0)下有一个乌龙数字的根源。

Mozilla上关于setTimeout的说明:
        https://developer.mozilla.org/en/DOM/window.setTimeout

(三)其它浏览器系列(Opera, Safari, Chrome)中的setTimeout
    和Mozilla系列中的基本一样,但是没有Mozilla系列中的多一个参数的BUG.


武林外传:使用setTimeout的小技巧

    (1)IE中给setTimeout中的调用函数传参数
        上面的分析可知,IE是不支持在setTimeout中给被调用的函数传参数的,为了浏览器世界的和谐,我们可以把函数调用参数包裹进新的匿名函数中。示例:
       
            function f(a){
                alert(a);
            }
            // setTimeout(f,50,'hello'); //用于非IE
            setTimeout(function(){f('hello')},50); //通用
            var str='hello';
            setTimeout(function(){f(str)},50); //通用
        


    (2)this问题
        setTimeout调用的函数被执行时的上下文是全局,而不再是调用setTimeout方法时的上下文。所以,setTimeout的第一个参数的函数被执行时其this是指向window的,如果需要保留调用setTimeout方法时的this,就需要把当时的this传进去。示例:
       
            function Person(name){
                this.name=name;
                var f=function(){alert('My name is '+this.name)};

                // setTimeout(f,50); //错误

                var THIS=this;
                setTimeout(function(){f.apply(THIS)},50); //正确,通用
                setTimeout(function(){f.call(THIS)},50); //正确,通用
            }
            new Person('Jack');
        


要说的就这些了。
发帖子不是脑力活,而是体力活,组织文字,写例子,排版,这些没技术含量的事情是最累人最耗时间的。
分享到:
评论
6 楼 clue 2010-09-26  
klovelovely 写道
setTimeout与setInterval还有一个区别,班门弄斧一下
就是setTimeout对于所传参数(无论是语句或是函数)执行完之后才会进行下一次时间间隔的计算。
而  setInterval则不会理会每次执行的参数是否完成,在一些对时间要求比较精确的环境下会更加有用,比如时间的计算。

拙见,多多指教!*^^*

你的理解错了,浏览器中的JS执行进程是单线程的,上一个JS任务未执行完成,是不会开始下一个任务的。

参考:
JavaScript的单线程性质以及定时器的工作原理
http://www.phpweblog.net/rainman/archive/2009/01/05/6267.html
5 楼 对酒当歌,人生几何 2010-09-26  
原来参数 是这么回事,顶楼主,比我留心。
4 楼 tizll521 2010-07-14  
受益非浅  看完了
3 楼 klovelovely 2010-06-25  
setTimeout与setInterval还有一个区别,班门弄斧一下
就是setTimeout对于所传参数(无论是语句或是函数)执行完之后才会进行下一次时间间隔的计算。
而  setInterval则不会理会每次执行的参数是否完成,在一些对时间要求比较精确的环境下会更加有用,比如时间的计算。

拙见,多多指教!*^^*
2 楼 soni 2010-01-25  
我知道这2个函数是属于dom的。但还真不知道这么多差异。
1 楼 cuixiping 2010-01-24  
javaeye的帖子显示不是用的等宽字体,所以在UBB模式下写的英文内容,出来之后就对不齐了,排版啊排版,累。

相关推荐

    setTimeout与setInterval在不同浏览器下的差异

    在不同浏览器下,这个函数被调用时 `arguments` 对象的行为出现了差异: - Internet Explorer (6, 7, 8) 不传递任何额外的参数给 `f`,因此 `arguments.length` 为 0。 - Opera (6, 7, 8) 将两个参数 "javascript" ...

    浅谈setTimeout 与 setInterval

    最新写代码中时,看到项目中有人用到了 setTimeout(fun,0),...这样就可以理解 setTimeout(fun,0) 了,它并不是代表立即执行该代码,除非任务队列为空(事实上,各个浏览器在实际执行这个的时候也是有差异了,比较新的浏

    浅谈对于“不用setInterval,用setTimeout”的理解

    在JavaScript编程中,`setTimeout`和`setInterval`是两个常用的定时器函数,用于在指定的时间后执行一段代码。尽管它们的基本功能相似,但在使用场景和性能上存在差异。`setTimeout`用于执行一次性的延迟操作,而`...

    仅IE不支持setTimeout/setInterval函数的第三个以上参数

    总的来说,了解不同浏览器对 `setTimeout` 和 `setInterval` 额外参数的支持情况是非常重要的,这对于编写兼容性良好的前端代码至关重要。在编写JavaScript代码时,应该尽量避免依赖这种非标准的行为,或者通过上面...

    setTimeout()与setInterval()方法区别介绍

    如果当前执行栈中有其他任务在运行,定时器可能会被推迟,导致实际的执行时间与预期不同。这种延迟对于`setTimeout()`来说影响相对较小,因为它只执行一次;但对于`setInterval()`来说,如果上一次执行还未完成,下...

    自定义js库,解决浏览器不兼容问题

    6. **定时器**:setTimeout和setInterval在某些情况下可能会出现不一致的行为,比如在页面卸载时。自定义库应考虑这些情况并提供更可靠的定时器解决方案。 7. **JSON处理**:虽然JSON是现代浏览器的标配,但老版本...

    javascript经典特效---浏览器毁灭者-请小心使用.rar

    9. **浏览器兼容性**:不同的浏览器对JavaScript的实现可能存在差异,某些极端的代码可能在某些浏览器上运行良好,而在其他浏览器上导致问题。 10. **性能优化**:为了避免上述问题,开发者通常会采用一些最佳实践...

    如何编写跨浏览器的javascript程序

    - `setTimeout`和`setInterval`在不同浏览器中可能存在精度问题,使用`requestAnimationFrame`可以得到更一致的结果。 10. **DOM操作**: - 不同浏览器的DOM API可能有所不同,如`getElementById`和`...

    对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!

    标题中的问题涉及到JavaScript的`setInterval`函数在不同浏览器,特别是火狐(Firefox)和Chrome中的行为差异。当用户在浏览器中切换标签时,`setInterval`的行为可能会变得不一致,这在描述中有所体现。IE浏览器...

    文字循环向上移动支持多浏览器

    标题提到的“文字循环向上移动支持多浏览器”意味着我们需要解决不同浏览器之间的兼容性差异,确保在主流的浏览器如Chrome、Firefox、Safari、Edge以及Internet Explorer上都能正常运行。传统的实现方式是通过CSS的`...

    JS最简单的滚动新闻,兼容IE6及其他主流浏览器

    这个滚动新闻的实现可能使用了条件注释、特征检测或者特定的CSS hack来解决IE6和其他浏览器之间的差异,确保在各种环境下都能稳定显示。 在JS中,我们可以创建一个数组存储新闻项,然后使用循环和定时器来改变显示...

    self-adjusting-interval:setInterval可以在浏览器,Node和React Native上运行,就像它应该具有的

    经过测试- Nodejs的浏览器React本机它是如何工作的Javascript是一种脚本语言,只能在一个进程上运行,因为setInterval和setTimeout都不准确,因为该进程可能忙于其他工作。 设置传统间隔将很快证明自己不准确,在此...

    javascript经典特效---浏览器详细报告.rar

    在浏览器环境下,Window对象作为全局对象,提供了一系列与用户交互相关的方法,如setTimeout、clearTimeout、alert、confirm等。 在性能优化方面,JavaScript开发者需要注意避免阻塞页面渲染,合理使用异步加载,...

    兼容IE、FireFox、Safari多浏览器的图片不间断滚动

    因此,为了实现跨浏览器兼容,我们可能需要使用一些回退策略或使用像jQuery这样的库来处理浏览器差异。 **JavaScript基础** 在JavaScript中,我们可以利用定时器(`setInterval`)来定期改变图片的位置,模拟滚动...

    支持IE与火狐的脚本特效,很多特效是不支持火狐浏览器的

    8. **定时器差异**:setTimeout和setInterval在不同浏览器中的执行精度可能会有所不同,需要适当调整代码以确保一致的行为。 综上所述,要实现"支持IE与火狐的脚本特效",开发者需要对各种兼容性问题有深入理解,并...

    IE和Firefox对JavaScript的兼容

    然而,由于不同的浏览器对其解析和执行的方式存在差异,尤其是IE(Internet Explorer)和Firefox,这导致了JavaScript在不同浏览器间的兼容性问题。这份文档“IE火狐的JavaScript兼容.doc”深入探讨了这些差异,并...

    js全兼容图片滚动代码

    这可能包括使用jQuery或其他库来抽象浏览器差异,或者使用条件注释和特性检测来针对不同浏览器编写不同的代码片段。 2. **CSS样式控制**:在JS中控制图片滚动,往往需要动态更改图片的CSS定位属性。例如,如果使用...

    Javascript在IE和FireFox中的不同表现

    - IE的`onreadystatechange`事件在某些情况下处理方式与Firefox不同。 7. **定时器**: - `setTimeout`和`setInterval`在IE中可能存在精度问题,而Firefox通常更准确。 8. **错误处理**: - IE使用`try...catch...

    支付宝生活助手导航代码兼容FF IE6789 等主流浏览器

    - **动画效果**:利用`setTimeout`、`setInterval`或jQuery的动画方法实现滑动导航效果。 4. **CSS预处理器**: - 使用Sass或Less编写可复用、结构化的CSS,编译后生成兼容各个浏览器的CSS代码。 5. **现代...

Global site tag (gtag.js) - Google Analytics