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 相关文章推荐
10款非常有用的 Ajax 插件分享
Mar 14 Javascript
Jquery获取和修改img的src值的方法
Feb 17 Javascript
JS跨域问题详解
Nov 25 Javascript
js如何实现点击标签文字,文字在文本框出现
Aug 05 Javascript
jquery+css3实现网页背景花瓣随机飘落特效
Aug 17 Javascript
IE9+已经不对document.createElement向下兼容的解决方法
Sep 14 Javascript
jQuery Easyui Datagrid实现单行的上移下移及保存移动的结果
Aug 15 Javascript
jQuery展示表格点击变色、全选、删除
Jan 05 Javascript
Angular.js中ng-include用法及多标签页面的实现方式详解
May 07 Javascript
QRCode.js:基于JQuery的生成二维码JS库的使用
Jun 23 jQuery
Angular 2 利用Router事件和Title实现动态页面标题的方法
Aug 23 Javascript
vue中的可拖拽宽度div的实现示例
Apr 08 Vue.js
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获取mysql数据库中的所有表名的代码
2011/04/23 PHP
54个提高PHP程序运行效率的方法
2015/07/19 PHP
关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析
2016/01/08 PHP
解析PHP的Yii框架中cookie和session功能的相关操作
2016/03/17 PHP
Yii2创建表单(ActiveForm)方法详解
2016/07/23 PHP
PHP DB 数据库连接类定义与用法示例
2019/03/11 PHP
Prototype使用指南之selector.js
2007/01/10 Javascript
JavaScript isPrototypeOf和hasOwnProperty使用区别
2010/03/04 Javascript
Jquery Ajax学习实例 向页面发出请求,返回XML格式数据
2010/03/14 Javascript
自定义函数实现IE7与IE8不兼容js中trim函数的问题
2015/02/03 Javascript
JavaScript代码性能优化总结篇
2016/05/15 Javascript
需要牢记的JavaScript基础知识
2016/09/25 Javascript
Angular 2父子组件之间共享服务通信的实现
2017/07/04 Javascript
Angularjs单选框相关的示例代码
2017/08/17 Javascript
JS严格模式知识点总结
2018/02/27 Javascript
js实现鼠标单击Tab表单切换效果
2018/05/16 Javascript
JS实现字符串中去除指定子字符串方法分析
2018/05/17 Javascript
AngularJS 多指令Scope问题的解决
2018/10/25 Javascript
微信小程序实现商城倒计时
2020/11/01 Javascript
超详细小程序定位地图模块全系列开发教学
2020/11/24 Javascript
vue实现禁止浏览器记住密码功能的示例代码
2021/02/03 Vue.js
[03:47]2015国际邀请赛第三日现场精彩回顾
2015/08/08 DOTA
[40:01]OG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
在Python中使用HTML模版的教程
2015/04/29 Python
Python实现批量压缩图片
2018/01/25 Python
python判断设备是否联网的方法
2018/06/29 Python
用Python批量把文件复制到另一个文件夹的实现方法
2019/08/16 Python
Python面向对象之Web静态服务器
2019/09/03 Python
tensorflow tf.train.batch之数据批量读取方式
2020/01/20 Python
Python requests接口测试实现代码
2020/09/08 Python
在pycharm中使用pipenv创建虚拟环境和安装django的详细教程
2020/11/30 Python
python 基于opencv去除图片阴影
2021/01/26 Python
HTML5进阶段内联标签汇总(小篇)
2016/07/13 HTML / CSS
停车场管理制度范本
2015/08/05 职场文书
gateway与spring-boot-starter-web冲突问题的解决
2021/07/16 Java/Android
MySQL远程无法连接的一些常见原因总结
2022/09/23 MySQL