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 相关文章推荐
XRegExp 0.2: Now With Named Capture
Nov 30 Javascript
CSS常用网站布局实例
Apr 03 Javascript
js使用eval解析json实例与注意事项分享
Jan 18 Javascript
JS面试题---关于算法台阶的问题
Jul 26 Javascript
浅析jsopn跨域请求原理及cors(跨域资源共享)的完美解决方法
Feb 06 Javascript
bootstrap警告框示例代码分享
May 17 Javascript
Vue二次封装axios为插件使用详解
May 21 Javascript
jQuery实现获取动态添加的标签对象示例
Jun 28 jQuery
ES6 中可以提升幸福度的小功能
Aug 06 Javascript
深入学习TypeScript 、React、 Redux和Ant-Design的最佳实践
Jun 17 Javascript
使用Typescript开发微信小程序的步骤详解
Jan 12 Javascript
JavaScript中关于预编译、作用域链和闭包的理解
Mar 31 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控制linux服务器常用功能 关机 重启 开新站点等
2012/09/05 PHP
一个php短网址的生成代码(仿微博短网址)
2014/05/07 PHP
实例介绍PHP删除数组中的重复元素
2019/03/03 PHP
使用laravel的migrate创建数据表的方法
2019/09/30 PHP
javascript下对于事件、事件流、事件触发的顺序随便说说
2010/07/17 Javascript
使用AngularJS中的SCE来防止XSS攻击的方法
2015/06/18 Javascript
JavaScript中的对象和原型(一)
2016/08/12 Javascript
详解vue-router基本使用
2017/04/18 Javascript
基于javascript 显式转换与隐式转换(详解)
2017/12/15 Javascript
关于express与koa的使用对比详解
2018/01/25 Javascript
axios对请求各种异常情况处理的封装方法
2018/09/25 Javascript
vue动态子组件的两种实现方式
2019/09/01 Javascript
原生js滑动轮播封装
2020/07/31 Javascript
JavaScript 防盗链的原理以及破解方法
2020/12/29 Javascript
Python中的类学习笔记
2014/09/23 Python
python执行shell获取硬件参数写入mysql的方法
2014/12/29 Python
python实现用户管理系统
2018/01/10 Python
关于Django ForeignKey 反向查询中filter和_set的效率对比详解
2018/12/15 Python
Python3 使用cookiejar管理cookie的方法
2018/12/28 Python
python实现控制电脑鼠标和键盘,登录QQ的方法示例
2019/07/06 Python
python分布式计算dispy的使用详解
2019/12/22 Python
Django+boostrap 美化admin后台的操作
2020/03/11 Python
智利最大的网上商店:Linio智利
2016/11/24 全球购物
Jacques Lemans德国:奥地利钟表品牌
2019/12/26 全球购物
解释一下ArrayList Vector和LinkedList的实现和区别
2013/04/26 面试题
电力安全事故反思
2014/04/27 职场文书
优秀教导主任事迹材料
2014/05/09 职场文书
2014年教师政治学习材料
2014/06/02 职场文书
试用期辞职信范文
2015/03/02 职场文书
2015年五一劳动节演讲稿
2015/03/18 职场文书
新学期开学标语2015
2015/07/16 职场文书
公司要求试用期员工提交“述职报告”,该怎么写?
2019/07/17 职场文书
详细谈谈MYSQL中的COLLATE是什么
2021/06/11 MySQL
mysql联合索引的使用规则
2021/06/23 MySQL
解析MySQL索引的作用
2022/03/03 MySQL
jdbc中自带MySQL 连接池实践示例
2022/07/23 MySQL