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');要说的就这些了。
发帖子不是脑力活,其实是体力活,组织文字,写例子,排版,这些没技术含量的事情是最累人最耗时间的。-----
这是我的一篇老文章了,写在博客里的,觉得可以拿到这里来和大家分享一下。
如果排版乱,可以到我的博客里看,那里的格式好控制些。
这里的发帖内容不仅不能预览,还不能修改。

解决方案 »

  1.   

    路过,不只是setTimeOut,很多类似的方法引用都涉及到参数传递问题!
    使用匿名函数封装一下还是不错的。
      

  2.   


    //修复bug1,使用window.setTimeout调用
    if(!+'\v1') {
        (function(f){
            window.setTimeout =f(window.setTimeout);
            window.setInterval =f(window.setInterval);
        })(function(f){
            return function(c,t){
                var a=[].slice.call(arguments,2);
                return f(function(){
                    c.apply(this,a)},t)
                }
        });
    }
      

  3.   

    我觉得这个差异相对来说不是很重要,因为一般情况下没人会给setTimeout传入两个
    以上的参数。相对来说搞清楚setTimeout在什么时候运行比了解这些细节末节要有用
    的多
      

  4.   

    java我本身就比较少用,但,学习啦
      

  5.   

    setTimeout与setInterval在不... [JavaScript]
      

  6.   

    我有个问题:就是使用定时器window.setInterval()时,然后弹出一个模式窗口,如:
    <input tyep="file"/>  选择文件,会堵塞定时器的正常运行,试问有什么解决方案没有!
      

  7.   

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

  8.   

    互联网公司招聘网站高级开发工程师,岗位职责:  
    1.参与或带领开发小组进行网站上各类产品的开发;
    2.参与网站性能调优。
    岗位要求:  
    1.3年以上网站开发经验,1年以上WEB2.0网站开发经验;
    2.精通.NET/C# 开发,精通CSS,熟悉SQL数据库设计及熟练应用SQL语言;
    3.熟悉网站产品开发流程,对网站产品的UI及用户体验有很好的认识;
    4.至少熟悉一种javascript主流基础开发包;
    5.有很高的网站程序开发热情,有一定的项目管理能力;
    6.能熟练阅读英文资料;
    7.良好的沟通能力,学习能力及团队合作精神。
    有意向的请发送简历至[email protected]
      

  9.   

    我有个问题:就是使用定时器window.setInterval()时,然后弹出一个模式窗口,如:
    <input tyep="file"/> 选择文件,会堵塞定时器的正常运行,试问有什么解决方案没有! 
     
      

  10.   

    不只是setTimeOut,很多类似的方法引用都涉及到参数传递问题!
    使用匿名函数封装一下还是不错的。
      

  11.   

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

  12.   

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

  13.   

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