﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Felix Woo &#187; setTimeout</title>
	<atom:link href="http://www.felixwoo.com/tag/settimeout/feed" rel="self" type="application/rss+xml" />
	<link>http://www.felixwoo.com</link>
	<description>世界因我存在</description>
	<lastBuildDate>Thu, 10 Nov 2011 11:54:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>对JavaScript调用堆栈和setTimeout用法的深入研究</title>
		<link>http://www.felixwoo.com/archives/244</link>
		<comments>http://www.felixwoo.com/archives/244#comments</comments>
		<pubDate>Thu, 15 Nov 2007 08:21:20 +0000</pubDate>
		<dc:creator>Felix</dc:creator>
				<category><![CDATA[开发技术]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[setTimeout]]></category>
		<category><![CDATA[堆栈]]></category>

		<guid isPermaLink="false">http://219.234.88.162:81/?p=244</guid>
		<description><![CDATA[Javascript中会经常用到setTimeout来推迟一个函数的执行，如： setTimeout(function(){alert("Hello World");},1000) 会在执行到这句话后延迟1秒钟来弹出alert窗口。那么再看这一段： function a&#40;&#41; &#123; setTimeout&#40;function&#40;&#41; &#123;alert&#40;1&#41;&#125;, 0&#41;; alert&#40;2&#41;; &#125; a&#40;&#41;; 注意这段代码中的setTimeout延迟设为了0，就是延迟0毫秒，貌似是不做任何延迟立刻执行，即1,2。但实际的执行结果确是2,1。为什么？这得从Javascript调用堆栈(call stack)和setTimeout的功能说起。 首先，JavaScript是单线程的，即同一时间只执行一条代码，所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。其次，和其他的编程语言一样，Javascript中的函数调用也是通过堆栈实现的。在执行函数a的时候，a先入栈，如果不给alert(1)加setTimeout，那么alert(1)第2个入栈，最后是alert(2)。但现在给alert(1)加上setTimeout后，alert(1)就被加入到了一个新的堆栈中等待，并“尽可能快”的执行。这个尽可能快就是指在a的堆栈完成后就立刻执行，因此实际的执行结果就是先alert(2)，再alert(1)。在这里setTimeout实际上是让alert(1)脱离了当前函数调用堆栈。看下面一个例子： &#60;input name=&#34;input&#34; onkeydown=&#34;alert(this.value)&#34; type=&#34;text&#34; value=&#34;a&#34; /&#62; 这样一段函数意图是每输入一个字符就把当前input里的所有字符都alert出来，但实际效果确是alert出按键之前的内容。这里，我们就可以利用setTimeout(0)来实现。 &#60;input onkeydown=&#34;var me=this; setTimeout(function(){alert(me.value)}, 0)&#34; name=&#34;input&#34; type=&#34;text&#34; value=&#34;a&#34; /&#62; 这样当onkeydown事件触发的时候，alert就被放入了下一个调用堆栈，一旦onkeydown事件触发的堆栈关闭后就开始执行。当然浏览器还有个onkeyup事件也可以实现我们的需求。 这样的setTimeout用法在实际项目中还是会时常遇到。比如浏览器会聪明的等到一个函数堆栈结束后才改变DOM，如果再这个函数堆栈中把页面背景先从白色设为红色，再设回白色，那么浏览器会认为DOM没有发生任何改变而忽略这两句话，因此我们可以通过setTimeout把“设回白色”函数加入下一个堆栈，那么就可以确保背景颜色发生过改变了（虽然速度很快可能无法被察觉）。 总之，setTimeout增加了Javascript函数调用的灵活性，为函数执行顺序的调度提供极大便利。 推荐阅读jQuery作者John的一篇文章：How JavaScript Timers Work，你会对JavaScript单线程本质和setTimeout以及setInterval有更加深刻的理解。]]></description>
			<content:encoded><![CDATA[<p>Javascript中会经常用到setTimeout来推迟一个函数的执行，如：</p>
<pre lang="javascript/csharp">setTimeout(function(){alert("Hello World");},1000)</pre>
<p>会在执行到这句话后延迟1秒钟来弹出alert窗口。那么再看这一段：</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> a<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    setTimeout<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
a<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>注意这段代码中的setTimeout延迟设为了0，就是延迟0毫秒，貌似是不做任何延迟立刻执行，即1,2。但实际的执行结果确是2,1。为什么？这得从Javascript调用堆栈(call stack)和setTimeout的功能说起。</p>
<p>首先，JavaScript是单线程的，即同一时间只执行一条代码，所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。其次，和其他的编程语言一样，Javascript中的函数调用也是通过堆栈实现的。在执行函数a的时候，a先入栈，如果不给alert(1)加setTimeout，那么alert(1)第2个入栈，最后是alert(2)。但现在给alert(1)加上setTimeout后，alert(1)就被加入到了一个新的堆栈中等待，并“尽可能快”的执行。这个尽可能快就是指在a的堆栈完成后就立刻执行，因此实际的执行结果就是先alert(2)，再alert(1)。在这里setTimeout实际上是让alert(1)脱离了当前函数调用堆栈。看下面一个例子：</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;input name=&quot;input&quot; onkeydown=&quot;alert(this.value)&quot; type=&quot;text&quot; value=&quot;a&quot; /&gt;</pre></div></div>

<p>这样一段函数意图是每输入一个字符就把当前input里的所有字符都alert出来，但实际效果确是alert出按键之前的内容。这里，我们就可以利用setTimeout(0)来实现。</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;input onkeydown=&quot;var me=this; setTimeout(function(){alert(me.value)}, 0)&quot; name=&quot;input&quot; type=&quot;text&quot; value=&quot;a&quot; /&gt;</pre></div></div>

<p>这样当onkeydown事件触发的时候，alert就被放入了下一个调用堆栈，一旦onkeydown事件触发的堆栈关闭后就开始执行。当然浏览器还有个onkeyup事件也可以实现我们的需求。</p>
<p>这样的setTimeout用法在实际项目中还是会时常遇到。比如浏览器会聪明的等到一个函数堆栈结束后才改变DOM，如果再这个函数堆栈中把页面背景先从白色设为红色，再设回白色，那么浏览器会认为DOM没有发生任何改变而忽略这两句话，因此我们可以通过setTimeout把“设回白色”函数加入下一个堆栈，那么就可以确保背景颜色发生过改变了（虽然速度很快可能无法被察觉）。</p>
<p>总之，setTimeout增加了Javascript函数调用的灵活性，为函数执行顺序的调度提供极大便利。</p>
<p>推荐阅读jQuery作者John的一篇文章：<a href="http://ejohn.org/blog/how-javascript-timers-work/" target="_blank">How JavaScript Timers Work</a>，你会对JavaScript单线程本质和setTimeout以及setInterval有更加深刻的理解。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.felixwoo.com/archives/244/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

