setTimeout和setInterval的浏览器兼容性分析


Posted in Javascript onFebruary 27, 2007

无意中测试AJAXRequest浏览器兼容性的时候,发现AJAXRequest.update方法在某些情况下在IE里有问题,经过测试找到是setTimeout和setInterval的问题。
问题出现在当调用AJAXRequest.update方法时,如果带了更新间隔及更新次数,那么在IE下面就会出现问题,具体表现为带了更新间隔时是函数工作,带上更新次数时函数无法在更新指定次数后停止执行。
测试几个例子之后找到了问题所在,在IE里,setTimeout和setInterval是不支持参数传递的。
演示地址:http://www.xujiwei.cn/demo/usetimer/
在Netscape的JavaScript参考中找到setTimeout的语法如下:

setTimeout 
Evaluates an expression or calls a function once after a specified number of milliseconds elapses. 
语法 
setTimeout(expression, msec) 
setTimeout(function, msec, arg1, ..., argN) 
参数 
expression  A string containing a JavaScript expression. 
msec  A numeric value or numeric string, in millisecond units.   
function  Any function.   
arg1, ..., argN  (Optional) The arguments, if any, passed to function.  

第二种使用方法就是定义了一个定时器,在执行时function时,将把调用setTimeout时定义的参数传递给function,但在IE中,并不支持这种方式的调用,也就是在执行function的时候,函数并没有接收到这些参数。如下面的例子:
<script type="text/javascript"> 
function show(str) { 
    alert("my site: "+str); 
} 
setTimeout(show,100,"www.xujiwei.cn"); 
</script>

在Firefox和Opera里,浏览器都能正确的弹出提示框显示字符串“my site: www.xujiwei.cn”,而在IE里,显示的则是“my site: undefined”,说明函数show并没有接收到参数str,所以显示出来就是一个未定义变量。
当然,如果在函数内部使用的变量是全局变量时,就不必要考虑这些问题,如:
<script type="text/javascript"> 
function show() { 
    // url是全局变量,函数正确执行 
    alert("my site: "+url); 
} 
var url="www.xujiwei.cn"; 
setTimeout(show,100); 
</script>

这段代码在IE和Firefox里都能正常工作,显示出“my site: www.xujiwei.cn”。
在变量是全局变量的情况下,可以使用语句段的方式来调用setTimeout,即使用第一种语法:
<script type="text/javascript"> 
function show(str) { 
    // url是全局变量,函数正确执行 
    alert("my site: "+str); 
} 
var url="www.xujiwei.cn"; 
setTimeout("show(url);",100); 
</script>

因为变量url是全局变量,因此定时器执行所定义的语句段“show(url);”能正确传递参数,但是如果url不是全局变量,而是一个局部变量时,执行结果就会出错了:
<script type="text/javascript"> 
function show(str) { 
    // url是全局变量,函数正确执行 
    alert("my site: "+str); 
} 
function test() { 
    var url="www.xujiwei.cn"; 
    setTimeout("show(url);",100); 
} 
test(); 
</script>

此时就会出错了,在函数test执行时,会提示url未定义,在执行定义的语句段“show(url);”时,上下文已经脱离了函数test,而url是在函数test内部定义的,所以在执行函数test的时候,变量url已经释放了。
如果要在setTimeout里面使用局部变量,并且解决在IE里的setTimeout不支持参数传递的问题,可以使用匿名函数,即在调用setTimeout时定义一个匿名函数,在这个函数内部进行原来需要进行的操作。
<script type="text/javascript"> 
function show(str) { 
    // url是全局变量,函数正确执行 
    alert("my site: "+str); 
} 
function test() { 
    var url="www.xujiwei.cn"; 
    setTimeout(function(){show(url);},100); 
} 
test(); 
</script>

在上面的例子中,调用setTimeout时定义了一个匿名函数,它的函数体是“show(url);”,因为已经定义了函数,所以在定时器调用这个函数时,变量url还是有引用的,因些函数可以正确执行,显示出字符串“my site: www.xujiwei.cn”。
总的来说,使用setTimeout或者setInterval时需要注意以下几点:
1. 定义定时器时如果是使用的表达示,那么其中的变量应该是全局变量,或者是一个直接的值,而不能是局部变量。
2. 定义定时器时如果是定义的调用函数,那么应该只写函数名,而不能加括号,如果加了就是定义返回值了。
3. 在IE里使用定时器时不能传递参数。
4. 如果要在IE里使用定时器时传递参数,可以使用匿名函数,在函数体中调用原来该调用的函数。

如有错误还请指正。

Javascript 相关文章推荐
Javascript 设计模式(二) 闭包
May 26 Javascript
最好用的省市二级联动 原生js实现你值得拥有
Sep 22 Javascript
js获取select默认选中的Option并不是当前选中值
May 07 Javascript
20个实用的JavaScript技巧分享
Nov 28 Javascript
JS简单验证上传文件类型的方法
Apr 17 Javascript
Bootstrap布局之栅格系统学习笔记
May 04 Javascript
Node.js 的模块知识汇总
Aug 16 Javascript
jQuery实现的监听导航滚动置顶状态功能示例
Jul 23 jQuery
详解如何使用koa实现socket.io官网的例子
Nov 04 Javascript
用node开发并发布一个cli工具的方法步骤
Jan 03 Javascript
微信小程序 可搜索的地址选择实现详解
Aug 28 Javascript
详解VUE中的插值( Interpolation)语法
Oct 18 Javascript
javascript里的条件判断
Feb 27 #Javascript
javascript第一课
Feb 27 #Javascript
javascript编程起步(第三课)
Feb 27 #Javascript
javascript编程起步(第二课)
Feb 27 #Javascript
javascript编程起步(第五课)
Feb 27 #Javascript
javascript编程起步(第四课)
Feb 27 #Javascript
javascript编程起步(第六课)
Feb 27 #Javascript
You might like
PHP 防恶意刷新实现代码
2010/05/16 PHP
解析php类的注册与自动加载
2013/07/05 PHP
使用PHP导出Word文档的原理和实例
2013/10/21 PHP
服务器上配置PHP运行环境教程
2015/02/12 PHP
php文档工具PHP Documentor安装与使用方法
2016/01/25 PHP
PHP错误机制知识汇总
2016/03/24 PHP
才发现的超链接js导致网页中GIF动画停止的解决方法
2007/11/02 Javascript
javascript 对象定义方法 简单易学
2009/03/22 Javascript
window.onload 加载完毕的问题及解决方案(下)
2009/07/09 Javascript
30个最好的jQuery 灯箱插件分享
2011/04/25 Javascript
JavaScript中的this实例分析
2011/04/28 Javascript
仿谷歌主页js动画效果实现代码
2013/07/14 Javascript
JS增加行复制行删除行的实现代码
2013/11/09 Javascript
jQuery on方法传递参数示例
2014/12/09 Javascript
javascript实现相同事件名称,不同命名空间的调用方法
2015/06/26 Javascript
浅析JS原型继承与类的继承
2016/04/07 Javascript
codeMirror插件使用讲解
2017/01/16 Javascript
js获取隐藏元素的宽高
2017/02/24 Javascript
微信小程序项目实践之主页tab选项实现
2018/07/18 Javascript
jquery将信息遍历到界面上实例代码
2020/01/21 jQuery
js实现计算器功能
2020/08/10 Javascript
[02:53]DOTA2英雄昆卡基础教程
2013/11/25 DOTA
[01:04:14]OG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[01:16:50]DOTA2-DPC中国联赛 正赛 Phoenix vs CDEC BO3 第一场 3月7日
2021/03/11 DOTA
玩转python爬虫之cookie使用方法
2016/02/17 Python
Python遍历目录并批量更换文件名和目录名的方法
2016/09/19 Python
python3 拼接字符串的7种方法
2018/09/12 Python
基于TensorFlow中自定义梯度的2种方式
2020/02/04 Python
Keras loss函数剖析
2020/07/06 Python
New Balance波兰官方商城:始于1906年,百年慢跑品牌
2017/08/15 全球购物
发现世界上最好的珠宝设计师:JewelStreet
2017/12/17 全球购物
《长城和运河》教学反思
2014/04/14 职场文书
2015年档案管理工作总结
2015/04/08 职场文书
企业员工辞职信范文
2015/05/12 职场文书
导游词之扬州大明寺
2019/10/09 职场文书
Mysql数据库按时间点恢复实战记录
2021/06/30 MySQL