今天群里发了一个问题,意思大致是setTimeout的回调函数加不加引号的区别
我试了一下,发现图里的注释都写错了:
setTimeout(fun1(a),1000) 是输出0-199
setTimeout(‘fun1(a)’,1000) 是输出200个200
群里还讨论了eval函数的使用,说是eval会创建临时作用域 eval结束其内变量不可访问,我没查到这个作用域,
感觉跟eval的关系不大,所以自己去看了一下setTimeout的用法,发现这个是必须要带引号的,然后自己也试了一些例子
function fun1(x) {
console.log(x);
}
fun2 = function (a) {
return 'fun1(' + a + ')'
}
//以下异步挨个单独测试
setTimeout('fun1(33)', 1000)//可异步--有延迟1000
setTimeout(fun1(22), 1000)//没异步--直接输出
setTimeout(fun2(22), 1000)//可异步--有延迟1000ms
fun3 = function () {
console.log(444);
}
setTimeout(fun3, 1000)//可异步--有延迟
测试结果是没有引号的,都直接同步运行,有引号的是异步,所以试了一个没引号但是return一个引号的,这个返回来的是异步,
总结一下
setTimeout只有第一个参数是字符串才会是回调函数,跟react中标签里的回调函数一样,不能自己写上括号,也可以不是字符串,这个函数可以是不加括号的函数,反正不能自己运行就完事了,但前提是该函数是不需要参数的比如:
fun3 = function () {
console.log(444);
}
setTimeout(fun3, 1000)
可以延迟输出
如果不是字符串,就相对于不是异步函数了,直接就运行了,比如
function fun1(x) {
console.log(x);
}
for(let a = 0 ; a < 200 ; a++){
setTimeout(fun1(a),1000)
}
输出0-199,每一次循环a都会被打印
如果是字符串就是正常的异步,等待回调启用
for(var a = 0 ; a < 200 ; a++){
setTimeout('fun1(a)',1000)
}
输出200个200,因为异步了,每个fun1(a)都在队列里等着,最后a都等于200了,然后全部一起输出了
*这种情况,eval是把字符串转成函数,相对于去掉字符串能正常运行
for(var a = 0 ; a < 200 ; a++){
setTimeout(eval('fun1(a)'),1000)
}
输出0-199,因为setTimeout第一个参数不是字符串,相对于这里直接同步运行eval()函数,然后直接把'fun1(a)'变成了fun1(a),
这个fun1(a)一出来就直接运行了,所以每一次a循环的时候,都直接输出了
*这种情况,setTimeout第一个参数是字符串,所以会把eval函数存起来异步运行,等a都200后才开始运行eval()--->'fun1(a)'--->fun1(a)--->200
for(var a = 0 ; a < 200 ; a++){
setTimeout("eval('fun1(a)')",1000)
}
输出200个200
仔细一想,平时写的setTimeout都是直接写箭头函数,忽略了这种形式,这样一看箭头函数也只是函数的定义,并没有执行,相对于存起来,等到计时结束后自动去加括号运行
setTimeout(()=>{
xxxx
},1000)