
本文共 2359 字,大约阅读时间需要 7 分钟。
图1:setTimeOut语法【1】
setTimeout的第一个参数分为3类,1.字符串代码 2.method 3.function【2】 。
1.字符串
function display(obj){ obj.style.display='none'; window.setTimeout("obj.style.display='inline'", 500);}
上面的这个代码会报错,obj is not defined。
因为setTimeout方法是window的方法,是个全局方法。执行这个方法的代码的作用域环境是window。
obj是当初display方法的参数传进来的,是个局部变量。在window下找不到obj这个变量所以报未定义。
2.封装后的方法传入 - method
function display(obj){ obj.style.display='none'; window.setTimeout("fn(obj)", 5000);}function fn(o){ o.style.display='inline'}
这样写 obj is not defined
原因和上面一样的,这儿调用的fn()是全局方法,它的参数obj在全局变量中找不到。
这里有一个注意点就是 window.setTimeout("fn(obj)", 5000); 这一句内的 fn(obj) 双引号双引号去掉以后会立即执行,当然,这个是错误的,举个例子
同时,抛出一个问题【3】
结果是立即输出0,1,2,3,4
【4】(下面是相应问题的回答,我做了部分修改和添加还有验证)网上关于JS预解释的文章也不少,在进入执行上下文阶段的时候函数并不会执行,简单来说就是当你声明这个函数的时候,只要不调用就不会执行,上下文里面只会保存着这个函数的引用,可以看做这个函数保存在内存中,只有到调用的时候函数才会执行。 你在for循环里面实际上相当于定义了5个定时器,但是js是单线程,这五个函数会被放到队列里面等待执行,你的函数内有立即执行函数,像你在for循环里面实际上相当于定义了5个定时器,但是js是单线程,这五个函数会被放到队列里面等待执行。(function(i) {
return function() { console.log(i);}})(i)
但是由于里面是立即执行函数,相当于执行上面一段,所以会立即就执行了,并且把i传了进去,等到这五个函数执行的时候,向上查找i,正好在这个立即调用函数的作用域里面查找到了i,所以会打印出0、1、2、3、4.
建议这样写(这是答主的提议)
但我个人建议这样写
每次将i作为参数传到setTimeout函数内(把(i)放在第一个函数后面也是这个原理,但不太严谨)
3.将function直接写在第一个参数处
function display(obj){ obj.style.diaplay='none'; window.setTimeout(function(){ obj.style.display='inline';},500); }
这种写法是把function直接写在了setTimeout的第一个参数位置,这样写就和display()形成了一个闭包。所以setTimeout执行function的时候display的作用域是存在的。
这样就会先去display()的作用域找obj这个变量,obj是当方法的参数传进来的,所以是能找到的。这样就能正确的执行这段代码。
PS1:第一个参数如果要用函数,一般要处理为setTimeOut(“function name()” ,time) (这时理解为匿名函数,也可以在里面直接执行一句话),或者setTimeOut(function name ,time) 或者setTimeOut(function name(){} ,time) ,setTimeOut(function name() ,time) 意味着执行返回值而不是函数,这时会立即执行函数,之后将返回值传入setTimeout方法
PS2: 有关timer=0
事实上,上面的代码并不是立即执行的,这是因为setTimeout
有一个最小执行时间,当指定的时间小于该时间时,浏览器会用最小允许的时间作为setTimeout
的时间间隔,也就是说即使我们把setTimeout
的延迟时间设置为0,被调用的程序也没有马上启动。
不同的浏览器实际情况不同,IE8和更早的IE的时间精确度是15.6ms。不过,随着HTML5的出现,在高级版本的浏览器(Chrome、ie9+等),定义的最小时间间隔是不得低于4毫秒,如果低于这个值,就会自动增加,并且在2010年及之后发布的浏览器中采取一致。
所以说,当我们写为 setTimeout(fn,0)
的时候,实际是实现插队操作,要求浏览器“尽可能快
”的进行回调,但是实际能多快就完全取决于浏览器了。
那setTimeout(fn, 0)
有什么用处呢?其实用处就在于我们可以改变任务的执行顺序!因为浏览器会在执行完当前任务队列中的任务,再执行setTimeout队列中积累的的任务。
通过设置任务在延迟到0s后执行,就能改变任务执行的先后顺序,延迟该任务发生,使之异步执行【5】。
参考文献
【1】菜鸟联盟 , Window setTimeout() 方法 , 2013
【2】 , ,, 2014.5.6
【3】鱼娟娟, , 2017.5.20
【4】尹光耀 , 2018.5.20【5】技术空间 . setTimeout 使用方法详解 . . 2017.2.23
发表评论
最新留言
关于作者
