setTimeout()用法总结
cy0707 opened this issue · 0 comments
cy0707 commented
前面
最进,在学习一个文字滚动效果的时候,在用setTimeout,总是出现作用域的问题,搜了好久,终于在一遍博文中发现了问题的所在。原文链接
超时调用(setTimeout)
setTimeout()方法,接受两个参数,要执行的代码和以毫秒表示的时间。其中第一个参数可以是一个包含javascript代码的字符串,也可以是一个函数。
//不建议传递字符串
setTimeout("alert('hello world')", 1000);
//推荐的调用方式
setTimeout(function(){
alert('hello world');
},1000)
因为传递字符串可能导致性能损失。因此不建议以字符串作为第一个参数。第二个参数是一个表示等待多长时间的毫秒数,因此一定时间内执行一段代码,为了控制要执行的代码,就有一个javascript任务队列。
调用setTimeout()之后,该方法会返回一个数值ID,表示超时调用,这个超时调用ID是执行代码的唯一标识符,可以通过它来取消超时调用。
//设置超时调用
var timeoutId = setTimeout(function() {
alert("hello world");
}, 1000)
//取消
clearTimeout(timeoutId );
//这个弹出框并不会弹出
间歇调用(setInterval)
间歇调用会按照指定的时间间隔重复执行代码,直到间歇调用被取消或者页面被卸载。其他同超时调用类似的。
间歇调用的问题,后一个间歇调用可能会在前一个间歇调用结束之前启动。
作用域问题
//在全局作用域下,调用 setTimeout
function fn(value){
alert("value=" + value);
}
setTimeout("fn(1)", 1000);
//在一个闭包里面调用
function outerFn(){
var value = 1;
function fn(){
alert("value=" + value);
value += 1;
}
setInterval("fn()", 3000);
}
outerFn(); //会出现错误:Uncaught ReferenceError: fn is not defined
//原因是fn()是以字符串的方式传递的,它的作用域是全局作用域,全局作用域是无法访问到fn()的。
//对于上面的这个问题,可以函数的引用传递
function outerFn(){
var value = 1;
function fn(){
alert("value=" + value);
value += 1;
}
setInterval(fn, 3000);
}
outerFn();
//但是这样又带来问题,如果想给fn传参数怎么办?可以像如下这样去写吗?
function outerFn(){
var value = 1;
function fn(n){
alert("value=" + n);
}
setTimeout(fn(5), 1000);
}
outerFn();
//答案是不可以的,函数只写函数名,是函数引用;后面加括号是函数执行
// setTimeout(fn, 1000); //fn的引用
// setTimeout(fn(5), 1000); //fn直接执行
//没有按照预期延迟1000毫秒执行fn(5),而是立刻就执行了。
// 这要注意和传递代码字符串的不同。
//如果确实有从外部传参的需要,该怎么办呢?
function outerFn(value){
function fn(){
alert("value=" + value);
}
setTimeout(fn, 1000);
}
outerFn(5);
是利用了闭包的原理,fn作为内部函数,是可以访问包含它的outerFn的作用域中的变量的,因此我们想给fn传参,只要给outerFn传参就可以了。这在传递的参数复杂(比如是一个复杂的json)的情况下,很有用途。