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 08 Javascript
JavaScript去除空格的三种方法(正则/传参函数/trim)
Feb 06 Javascript
Jquery封装tab自动切换效果的具体实现
Jul 13 Javascript
JavaScript实现按照指定长度为数字前面补零输出的方法
Mar 19 Javascript
JavaScript实现鼠标滑过图片变换效果的方法
Apr 16 Javascript
js实现图片缓慢放大缩小效果
Aug 02 Javascript
js实现日历的简单算法
Jan 24 Javascript
Vue.js常用指令的使用小结
Jun 23 Javascript
Vim快速合并行及vim 将文件所有行合并到一行
Nov 27 Javascript
vue mounted组件的使用
Jun 18 Javascript
vue spa应用中的路由缓存问题与解决方案
May 31 Javascript
vue 组件销毁并重置的实现
Jan 13 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的FTP学习(三)
2006/10/09 PHP
首页四格,首页五格For6.0(GBK)(UTF-8)[12种组合][9-18][版主安装测试通过]
2007/09/24 PHP
零基础php编程好学吗
2019/10/11 PHP
表单提交时自动复制内容到剪贴板的js代码
2007/03/16 Javascript
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
2013/01/16 Javascript
js 获取class的元素的方法 以及创建方法getElementsByClassName
2013/03/11 Javascript
JS清除IE浏览器缓存的方法
2013/07/26 Javascript
使用时间戳解决ie缓存的问题
2014/08/20 Javascript
Javascript中call与apply的学习笔记
2014/09/22 Javascript
JavaScript判断手机号运营商是移动、联通、电信还是其他(代码简单)
2015/09/25 Javascript
vue双向数据绑定原理探究(附demo)
2017/01/17 Javascript
AngularJS中$injector、$rootScope和$scope的概念和关联关系深入分析
2017/01/19 Javascript
AngularJS基于provider实现全局变量的读取和赋值方法
2017/06/28 Javascript
vue如何将v-for中的表格导出来
2018/05/07 Javascript
微信小程序自定义prompt组件步骤详解
2018/06/12 Javascript
详解vue几种主动刷新的方法总结
2019/02/19 Javascript
解决webpack多页面内存溢出的方法示例
2019/10/08 Javascript
vue element table中自定义一些input的验证操作
2020/07/18 Javascript
原生js实现分页效果
2020/09/23 Javascript
解决vue elementUI 使用el-select 时 change事件的触发问题
2020/11/17 Vue.js
利用Python绘制数据的瀑布图的教程
2015/04/07 Python
pygame实现弹力球及其变速效果
2017/07/03 Python
Python2实现的LED大数字显示效果示例
2017/09/04 Python
解决Python字典写入文件出行首行有空格的问题
2017/09/27 Python
Python模拟自动存取款机的查询、存取款、修改密码等操作
2018/09/02 Python
Python使用Selenium爬取淘宝异步加载的数据方法
2018/12/17 Python
浅谈Selenium+Webdriver 常用的元素定位方式
2021/01/13 Python
中国旅游网站:同程旅游
2016/09/11 全球购物
信用社员工先进事迹材料
2014/02/04 职场文书
师说教学反思
2014/02/07 职场文书
学生不讲诚信检讨书
2014/09/29 职场文书
2014年团委工作总结
2014/11/13 职场文书
大学生党性分析材料
2014/12/19 职场文书
给校长的建议书作文300字
2015/09/14 职场文书
如何起草一份正确的合伙创业协议书?
2019/07/04 职场文书
浅谈Go语言多态的实现与interface使用
2021/06/16 Golang