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


Posted in Javascript onJanuary 24, 2010

。(新手可能认为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');

要说的就这些了。
发帖子不是脑力活,其实是体力活,组织文字,写例子,排版,这些没技术含量的事情是最累人最耗时间的。
Javascript 相关文章推荐
jQuery 对象中的类数组操作
Apr 27 Javascript
jqGrid日期格式的判断示例代码(开始日期与结束日期)
Nov 08 Javascript
JS面向对象(3)之Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
Feb 25 Javascript
javascript事件冒泡简单示例
Jun 20 Javascript
HTML5 实现的一个俄罗斯方块实例代码
Sep 19 Javascript
快速解决Vue项目在IE浏览器中显示空白的问题
Sep 04 Javascript
Angular6 发送手机验证码按钮倒计时效果实现方法
Jan 08 Javascript
微信小程序 调用远程接口 给全局数组赋值代码实例
Aug 13 Javascript
layui 对table中的数据进行转义的实例
Sep 12 Javascript
layer iframe 设置关闭按钮的方法
Sep 12 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
Jun 17 Javascript
Vue实现计算器计算效果
Aug 17 Javascript
js 模拟实现类似c#下的hashtable的简单功能代码
Jan 24 #Javascript
jQuery 1.4 15个你应该知道的新特性(译)
Jan 24 #Javascript
优化javascript的执行速度
Jan 23 #Javascript
window.onbeforeunload方法在IE下无法正常工作的解决办法
Jan 23 #Javascript
JQuery 1.4 中的Ajax问题
Jan 23 #Javascript
用JS写的一个TableView控件代码
Jan 23 #Javascript
JQuery 操作Javascript对象和数组的工具函数小结
Jan 22 #Javascript
You might like
PHP 图片水印类代码
2012/08/27 PHP
php实现简单洗牌算法
2013/06/18 PHP
php使用gzip压缩传输js和css文件的方法
2015/07/29 PHP
PHP程序员的技术成长规划
2016/03/25 PHP
使用php完成常见的文件上传功能(推荐)
2017/01/13 PHP
laravel 关联关系遍历数组的例子
2019/10/10 PHP
经典海量jQuery插件 大家可以收藏一下
2010/02/07 Javascript
JS左右无缝滚动(一般方法+面向对象方法)
2012/08/17 Javascript
jQuery 获取浏览器所在的IP地址的小例子
2013/11/08 Javascript
jquery中radio checked问题
2015/03/16 Javascript
javascript封装addLoadEvent实现页面同时加载执行多个函数的方法
2016/07/25 Javascript
Bootstrap Table表格一直加载(load)不了数据的快速解决方法
2016/09/17 Javascript
jQuery插件FusionWidgets实现的Cylinder图效果示例【附demo源码】
2017/03/23 jQuery
JS实现预加载视频音频/视频获取截图(返回canvas截图)
2017/10/09 Javascript
Javascript读写cookie的实例源码
2019/03/16 Javascript
浅析webpack-bundle-analyzer在vue-cli3中的使用
2019/10/23 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
微信小程序自定义底部弹出框动画
2020/11/18 Javascript
vue实现图书管理系统
2020/12/29 Vue.js
Vue包大小优化的实现(从1.72M到94K)
2021/02/18 Vue.js
Python 字典(Dictionary)操作详解
2014/03/11 Python
分享Python开发中要注意的十个小贴士
2016/08/30 Python
python监控linux内存并写入mongodb(推荐)
2017/09/11 Python
Python numpy实现二维数组和一维数组拼接的方法
2018/06/05 Python
python3 读取Excel表格中的数据
2018/10/16 Python
使用Python爬取小姐姐图片(beautifulsoup法)
2021/02/11 Python
加拿大领先的优质厨具产品在线购物网站:Golda’s Kitchen
2017/11/17 全球购物
英国手工布艺沙发在线购买:Sofas & Stuff
2018/03/02 全球购物
实习单位接收函
2014/01/11 职场文书
师范毕业生自我鉴定
2014/01/15 职场文书
保险专业大学生职业规划书
2014/03/03 职场文书
电教室标语
2014/06/20 职场文书
流动人口婚育证明范本
2014/09/26 职场文书
建筑工程挂靠协议书
2016/03/23 职场文书
Redis集群新增、删除节点以及动态增加内存的方法
2021/09/04 Redis
js判断两个数组相等的5种方法
2022/05/06 Javascript