<?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>随网之舞JavaScript</title>
	<atom:link href="http://dancewithnet.com/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://dancewithnet.com</link>
	<description>WEB Design{HTML:CSS:Javascript:DOM:AJAX:PHP:Usability}/Viewpoint/Photo/Food/Mood</description>
	<lastBuildDate>Mon, 18 Jul 2011 02:45:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>动态加载JavaScript的小实践</title>
		<link>http://dancewithnet.com/2009/11/05/a-little-practice-about-js-lazy-load/</link>
		<comments>http://dancewithnet.com/2009/11/05/a-little-practice-about-js-lazy-load/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 16:56:30 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Loader]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1488</guid>
		<description><![CDATA[动态加载JavaScript文件和CSS资源为Web前端开发提供了巨大的灵活性，同时也实现了lazy load和按需加载，相比XMLHttpRequest而言其没有跨域的限制使其广泛应用。其基本原理是：在页面DOMReady后，利用... ]]></description>
			<content:encoded><![CDATA[<p>动态加载JavaScript文件和CSS资源为Web前端开发提供了巨大的灵活性，同时也实现了lazy load和按需加载，相比XMLHttpRequest而言其没有跨域的限制使其广泛应用。其基本原理是：在页面DOMReady后，利用JavaScript把指定文件路径的script和link元素插入到页面中，然后判断其加载状态再进行继续操作。</p>
<p><span id="more-1488"></span></p>
<p><a href="http://developer.yahoo.com/yui/3/get/">YUI的Get</a>就专门提供了一套动态加载的机制，是YUI最基础的功能之一。在YUI中利用Get加载JavaScript和CSS资源会在HTML的head节点中插入如下代码：</p>
<pre><code>&lt;script id="..." type="text/javascript" src="some.js"&gt;&lt;/script&gt;
&lt;link id="..." type="text/css" rel="stylesheet" href="some.css"&gt;
</code></pre>
<p>当页面编码和JavaScript或CSS资源编码不一致时，常见的方法是通过charset属性声明其编码，比如页面是gb2312，而资源文件为utf-8，则设置编码后其插入的代码是</p>
<pre><code><span>//YUI3.0.0 和 YUI 2.8.0中</span>
&lt;script id="..." type="text/javascript" src="some.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;link id="..." type="text/css" rel="stylesheet" href="some.css" charset="utf-8"&gt;
</code></pre>
<p>然而，<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/in-gb2312.html">在IE的一些特殊情况下加载JavaScript时，当你刷新页面时会看到状态栏上有如下的错误提示</a>：<br /><img src="http://dancewithnet.com/wp-content/uploads/2009/11/yui-loader-bug-in-ie.png" alt="YUI3.0.0动态加载JavaScript的bug" title="YUI3.0.0动态加载JavaScript的bug" width="593" height="460" class="alignnone size-full wp-image-1489" /></p>
<p>当你<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/random-in-gb2312.html">通过随机参数让JavaScript文件不缓存</a>时，或者<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/fixed-in-gb2312.html">让script元素中的charset属性位于src属性之前（比如利用YUI2.8.0之前版本加载）</a>就不会有这个错误提示。所以，这个问题可能是IE的缓存解码机制的bug，也可以看着是<a href="http://yuilibrary.com/projects/yui3/ticket/2528363">YUI的bug（已经提交给YUI开发团队，将在3.1.0中解决）</a>。</p>
<p>因此，动态添加script或CSS资源时，把charset放在资源路径前面是最佳实践。<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/fixed-in-gb2312.html">对于YUI，暂时可以这样修改源码来修复</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2009/11/05/a-little-practice-about-js-lazy-load/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>《JavaScript语言精粹》</title>
		<link>http://dancewithnet.com/2009/04/02/javascript-the-good-parts/</link>
		<comments>http://dancewithnet.com/2009/04/02/javascript-the-good-parts/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 15:45:57 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[Douglas Crockford]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[书评]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2009/04/02/javascript-the-good-parts/</guid>
		<description><![CDATA[本书的作者Douglas Crockford是JavaScript开发社区最知名的权威，JavaScript的发明人Brendan Eich说他是“Yoda of lambda programming and JavaScript（lambda编程和JavaScript的精神领袖）”。他不仅仅给我们带来了JSON、... ]]></description>
			<content:encoded><![CDATA[<p>本书的作者<a href="http://dancewithnet.com/2009/03/29/douglas-crockford/">Douglas Crockford</a>是JavaScript开发社区最知名的权威，JavaScript的发明人Brendan Eich说他是“Yoda of lambda programming and JavaScript（lambda编程和JavaScript的精神领袖）”。他不仅仅给我们带来了JSON、JSLint、JSMin和ADSafe等等在JavaScript开发领域应用广泛且影响深远的作品，更重要的是给我们带来了受益终身的利用JavaScript进行高效开发的思想和风格，这就是本书的重要意义。</p>
<p>JavaScript曾是“世界上最被误解的语言”，因为它担负太多的特性，包括糟糕的交互和失败的设计，但随着Ajax的到来，JavaScript“从最受误解的编程语言演变为最流行的语言”，这除了幸运之外，至少还说明它是一个不错的语言。Douglas Crockford在这本书中剥除JavaScript糟糕的外衣，抽离出一个具有更好可靠性、可读性和可维护性的JavaScript子集，让你看到一门优雅的、轻量级的和非常富有表现力的语言。他从语法、对象、函数、继承、数组、正则表达式、方法、样式和优美的特性这9个方面来呈现这门语言真正的精华，这是语言最本质最优雅的部分，通过它们完全可以构建出高效的代码。他还通过附录列出了这门语言的糟粕和鸡肋部分，且告诉你如何避免它们。最后还介绍了JSLint，通过它的检验，能有效的保障我们写出优美高效的代码。</p>
<p><span id="more-1445"></span>
<p>这是一本厚积薄发“薄”大精深的书籍，Douglas Crockford仅仅用了160页来道出JavaScript的语言本质，值得任何正在或者想从事JavaScript开发的人阅读，并且非常需要反复阅读。学习、理解、实践大师的思想，我们才可能站在巨人的肩上，才有机会超越大师，这本书就是开始。</p>
<p>我很高兴和淘宝UED的前端主管小马（赵泽欣）一起来翻译这本书，去年近5个月的翻译时间是一个非常艰苦而又痛快的学习过程。我们冒着“犯罪”的危险完成了翻译，现在我也很惶恐的推荐给大家，希望我们的努力能让读者读出本书的精华，更要读懂JavaScript的语言精华。</p>
<p>感谢你的关注、阅读、建议和批评。</p>
<ol>
<li><a href="http://www.china-pub.com/195292">购买《JavaScript语言精粹》</a></li>
<li>样章阅读
<ol>
<li><a href="http://images.china-pub.com/ebook195001-200000/195292/ch01.pdf">第一章. 精华</a></li>
<li><a href="http://images.china-pub.com/ebook195001-200000/195292/ch10.pdf">第十章. 优美的特性</a></li>
</ol>
</li>
<li><a href="http://dancewithnet.com/javascript-the-good-parts-errata/">勘误表</a></li>
<li><a href="http://ued.taobao.com/blog/2009/04/02/javascript_good_part_tw/">淘宝UED Blog：《JavaScript语言精粹》译者序及样章试读</a></li>
<li><a href="http://dancewithnet.com/2009/03/29/douglas-crockford/">JavaScript大牛：Douglas Crockford</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2009/04/02/javascript-the-good-parts/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>JavaScript大牛：Douglas Crockford</title>
		<link>http://dancewithnet.com/2009/03/29/douglas-crockford/</link>
		<comments>http://dancewithnet.com/2009/03/29/douglas-crockford/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 14:07:46 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[互联网 & IT]]></category>
		<category><![CDATA[Douglas Crockford]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[牛人]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2009/03/29/douglas-crockford/</guid>
		<description><![CDATA[Douglas Crockford是JavaScript开发社区最知名的权威，是JSON、JSLint、JSMin和ADSafe之父，是《JavaScript：The Good Parts》（英文版、中文版）的作者。JavaScript的发明人Brendan Eich说他是“Yoda of lambda programming a... ]]></description>
			<content:encoded><![CDATA[<p>Douglas Crockford是JavaScript开发社区最知名的权威，是<a href="http://www.json.org/json-zh.html">JSON</a>、<a href="http://www.jslint.com/">JSLint</a>、<a href="http://www.crockford.com/javascript/jsmin.html">JSMin</a>和<a href="http://www.adsafe.org/">ADSafe</a>之父，是《JavaScript：The Good Parts》（<a href="http://www.china-pub.com/43541">英文版</a>、<a href="http://www.china-pub.com/195292">中文版</a>）的作者。<a href="http://zh.wikipedia.org/wiki/Brendan_Eich">JavaScript的发明人Brendan Eich</a>说他是“<a href="http://zh.wikipedia.org/w/index.php?title=尤達&amp;variant=zh-cn">Yoda</a> of <a href="http://zh.wikipedia.org/wiki/&Lambda;演算">lambda</a> programming and JavaScript（lambda编程和JavaScript的精神领袖）”。他同时也服务于<a href="http://zh.wikipedia.org/w/index.php?title=Ecma国际&amp;variant=zh-cn">ECMA</a>的JavaScript2.0技术委员会（TC39）。其个人站点和Blog是<a href="http://www.crockford.com/">http://www.crockford.com/</a>和<a href="http://profiles.yahoo.com/blog/GSBHPXZFNRM2QRAP3PXNGFMFVU">http://profiles.yahoo.com/blog/GSBHPXZFNRM2QRAP3PXNGFMFVU</a>。</p>
<p>Douglas Crockford现在是Yahoo的资深JavaScript架构师，曾在<a href="http://zh.wikipedia.org/w/index.php?title=Atari&amp;variant=zh-cn">Atari</a>公司（视频游戏工业的领袖）开发了办公自动化系统，同时也完成了对于游戏和音乐的研究；曾任<a href="http://en.wikipedia.org/wiki/Lucasfilm">Lucasfilm（卢卡斯）电影公司</a>技术总监；在<a href="http://zh.wikipedia.org/w/index.php?title=派拉蒙電影公司&amp;variant=zh-cn">Paramount（派拉蒙）公司</a>任职过新媒体执行主管；在电气社区，通常为人所知的是communities.com的创始人兼首席执行官；他还创办了State软件公司并作为该公司CTO，这也是他发现JSON时所在的地方。他同时也对<a href="http://en.wikipedia.org/wiki/Blissymbolics">Blissymbolics</a>非常感兴趣，这是一种图形、象征性的语言，并且对<a href="http://crockford.com/pwl/">永久减肥（Permanent Weight Loss）</a>做过研究。</p>
<p><span id="more-1442"></span>
<p><a href="http://yuilibrary.com/">YUI</a>团队2008年底的合影，中间的长者即为Douglas Crockford：<a href="http://www.flickr.com/photos/equanimity/2126487011/sizes/l/"><img src="http://dancewithnet.com/wp-content/uploads/2009/03/yui-team.jpg" alt="yui-team" title="yui-team" width="500" height="337" class="alignnone size-full wp-image-1443" /></a></p>
<p>Douglas Crockford作为JavaScript开发社区的Guru，其众多的在JavaScript开发方面的研究成果被广泛的应用，而他的思想也深深的影响了整个JavaScript应用和发展。学习、理解、实践大师的思想，我们才可能站在巨人的肩上，才有机会超越，所以下面列表是一个开始：</p>
<ol>
<li><a href="http://javascript.crockford.com/javascript.html">JavaScript: The Wrrrld&#8217;s Most Misunderstood Programming Language</a>       <br />中文：<a href="http://shiningray.cn/javascript-the-worlds-most-misunderstood-programming-language.html">JavaScript:世界上最被误解的语言</a> </li>
<li><a href="http://javascript.crockford.com/popular.html">The World&#8217;s Most Misunderstood Programming Language Has Become the World&#8217;s Most Popular Programming Language</a>       <br />中文：<a href="http://www.ajaxjs.com/popular.htm">JavaScript：从最受误解的编程语言演变为最流行的语言</a> </li>
<li><a href="http://www.crockford.com/html/">A Survey of the JavaScript Programming Language</a>       <br />中文：<a href="http://svza.blogspot.com/2007/03/javascript_09.html">纵览 JavaScript语言</a> </li>
<li><a href="http://javascript.crockford.com/code.html">Code Conventions for the JavaScript Programming Language</a>       <br />中文：<a href="http://dancewithnet.com/snapshot/code-conventions-for-the-javascript-programming-language/">JavaScript程序编码规范</a> </li>
<li><a href="http://javascript.crockford.com/little.html">The Little JavaScripter</a>       <br />对《The Little Schemer》一书的讨论，并作了以JavaScript代替Scheme的尝试 </li>
<li><a href="http://javascript.crockford.com/private.html">Private Members in JavaScript</a>       <br />中文：<a href="http://shiningray.cn/private-members-in-javascript.html">JavaScript中的私有成员</a> </li>
<li><a href="http://javascript.crockford.com/prototypal.html">Prototypal Inheritance in JavaScript</a>       <br />中文：<a href="http://svza.blogspot.com/2007/03/javascript_14.html">在JavaScript实现基于原型的继承</a> </li>
<li><a href="http://www.crockford.com/html/">Classical Inheritance in JavaScript</a>       <br />中文：<a href="http://svza.blogspot.com/2007/03/javascript_4663.html">在JavaScript中实现基于类模式的继承</a> </li>
<li><a href="http://javascript.crockford.com/remedial.html">Remedial JavaScript</a>       <br />过快的标准化导致JavaScript在开发过程中未得到足够的优化，当前它仍存在一些问题，本文提出了一些补救的措施 </li>
<li><a href="http://javascript.crockford.com/script.html">JavaScript and HTML Script Tags</a>       <br />中文：<a href="http://www.dreamdu.com/blog/2008/08/08/script/">JavaScript与HTML的Script标签</a> </li>
<li><a href="http://javascript.crockford.com/memory/leak.html">JScript Memory Leaks</a>       <br />中文：<a href="http://svza.blogspot.com/2007/06/jscript.html">JScript的内存泄漏</a> </li>
<li><a href="http://javascript.crockford.com/tdop/tdop.html">Top Down Operator Precedence</a>       <br />自顶向下的运算符优先级，这是Douglas Crockford为<a href="http://www.china-pub.com/37838">《Beautiful Code（代码之美）》</a>而写，位于书中第九章 </li>
<li><a href="http://javascript.crockford.com/style1.html">The Elements of JavaScript Style, Parts One</a> and <a href="http://javascript.crockford.com/style2.html">Two</a>       <br />中文：<a href="http://dancewithnet.com/2008/01/26/the-elements-of-javascript-style-part-one/">JavaScript的风格要素1</a>和<a href="http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/">2</a> </li>
<li><a href="http://dancewithnet.com/snapshot/minification-v-obfuscation/">Minification v. Obfuscation</a> </li>
<li><a href="http://dancewithnet.com/snapshot/synchronous-v-asynchronous/">Synchronous v. Asynchronous</a> </li>
<li><a href="http://dancewithnet.com/snapshot/with-statement-considered-harmful/">with Statement Considered Harmful</a> </li>
<li><a href="http://dancewithnet.com/snapshot/global-domination/">Global Domination</a> </li>
<li><a href="http://dancewithnet.com/snapshot/global-domination-part-two/">Global Domination, Part Two</a> </li>
<li><a href="http://dancewithnet.com/snapshot/for-in-intrigue/">for in Intrigue</a> </li>
<li><a href="http://dancewithnet.com/snapshot/javascript-we-hardly-new-ya/">JavaScript, We Hardly new Ya</a>       <br />中文：<a href="http://ued.taobao.com/blog/2007/05/15/%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BC%9A%E5%86%99javascript%E5%90%97%EF%BC%9F/">JavaScript的new，好久不见啊</a> </li>
<li><a href="http://dancewithnet.com/snapshot/json-and-browser-security/">JSON and Browser Security</a>       <br />中文：<a href="http://www.javaeye.com/topic/95569">JSON和浏览器安全</a> </li>
<li><a href="http://dancewithnet.com/snapshot/id-rather-switch-than-fight/">I’d Rather switch Than Fight!</a> </li>
<li><a href="http://dancewithnet.com/snapshot/premature-standardization/">The Only Thing We Have To Fear Is Premature Standardization</a>       <br />中文：<a href="http://ued.taobao.com/blog/2008/08/15/the_only_thing_we_have_to_fear_is_premature_standardization/">不成熟的标准化是我们唯一惧怕的</a> </li>
<li><a href="http://dancewithnet.com/snapshot/when-you-cant-count-on-your-numbers/">When You Can&#8217;t Count On Your Numbers</a> </li>
<li><a href="http://www.crockford.com/html/">Fixing HTML</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://sp42.javaeye.com/blog/145268">中文</a> </li>
<li><a href="http://profiles.yahoo.com/blog/GSBHPXZFNRM2QRAP3PXNGFMFVU?eid=r4TzWT86mnkHWVlA8n1uJxy4n8o1AFAHZgOFD4swhgwmbEsz9Q">HTML4.2</a> </li>
<li><a href="http://www.slideshare.net/douglascrockford/ajax-security-255587">Ajax security</a><sup>幻灯片</sup> </li>
<li>JavaScript: The Good Parts</a><sup>视频，2009.03在Google的演讲</sup>：
<ol>
<li><a href="http://google-code-updates.blogspot.com/2009/03/doug-crockford-javascript-good-parts.html">38 minutes</a><sup>视频位于Youtube上</sup> </li>
<li><a href="http://www.slideshare.net/rajivmordani/good-parts-of-javascript-douglas-crockford-presentation">幻灯片</a><sup>和ajax world 2008版本一样</sup> </li>
</ol>
</li>
<li>The Mashup Problem and Google Gears<sup>视频</sup></a>
<ol>
<li><a href="http://video.google.com/videoplay?docid=452089494323007214">44 minutes</a> | <a href="http://vp.video.google.com/videodownload?version=0&amp;secureurl=TgAAAI8fZJkCVfmUhmWs1sp-jHVMpmbggk2J4l6edqJ46szRcc1EuI-SIMFbF54vyJfvcF4wjN2LJW1gLuXc6NP4VYujbDM87GKIfh-5R5Ppo0Ga&amp;sigh=287gGBtLhHoYSTDCpAZGISu7TFE">MP4 download</a> </li>
</ol>
</li>
<li>The JavaScript Programming Language<sup>视频</sup>：
<ol>
<li><a href="http://video.yahoo.com/video/play?vid=111593">Part 1: 31 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-1.m4v">M4V download</a> </li>
<li><a href="http://video.yahoo.com/video/play?vid=111594">Part 2: 31 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-2.m4v">M4V download</a> </li>
<li><a href="http://video.yahoo.com/video/play?vid=111595">Part 3: 29 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-3.m4v">M4V download</a> </li>
<li><a href="http://video.yahoo.com/video/play?vid=111596">Part 4: 20 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-4.m4v">M4V download</a> </li>
<li><a href="http://www.slideshare.net/guestceb98b/the-javascript-programming-language">幻灯片</a> </li>
</ol>
</li>
<li>An Inconvenient API: The Theory of the Dom<sup>视频</sup>：
<ol>
<li><a href="http://video.yahoo.com/video/play?vid=111582">Part 1 (31 minutes)</a> </li>
<li><a href="http://video.yahoo.com/video/play?vid=111583">Part 2 (21 minutes)</a> </li>
<li><a href="http://video.yahoo.com/video/play?vid=111584">Part 3 (26 minutes)</a> </li>
<li><a href="http://www.slideshare.net/kavenyan/the-theory-of-the-dom">幻灯片</a> </li>
</ol>
</li>
<li>Advanced JavaScript<sup>视频</sup>：
<ol>
<li><a href="http://video.yahoo.com/video/play?vid=111585">Part 1: 31 minutes</a> </li>
<li><a href="http://video.yahoo.com/video/play?vid=111586">Part 2: 25 minutes</a> </li>
<li><a href="http://video.yahoo.com/video/play?vid=111587">Part 3: 11 minutes</a> </li>
<li><a href="http://www.slideshare.net/Adieu/advanced-javascript">幻灯片</a> </li>
</ol>
</li>
<li>Quality<sup>视频，YAHOO Frontend Summit 2007</sup>：
<ol>
<li><a href="http://video.yahoo.com/watch/529579/2724346">48 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-quality.m4v">M4V download</a> </li>
</ol>
</li>
<li>JavaScript: The Good Stuff<sup>视频</sup>：
<ol>
<li><a href="http://video.yahoo.com/watch/630959/2974197">39 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-goodstuff.m4v">M4V download</a> </li>
</ol>
</li>
<li>The State of Ajax<sup>视频</sup>：
<ol>
<li><a href="http://video.yahoo.com/watch/1382941/4760685">38 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/stateofajax.m4v">M4V download</a> </li>
</ol>
</li>
<li>Ajax Performance<sup>视频</sup>：
<ol>
<li><a href="http://video.yahoo.com/watch/4156174/11192533">38 minutes</a> | <a href="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-performance.m4v">M4V download</a> </li>
<li><a href="http://www.slideshare.net/kavenyan/ajax-performance">幻灯片</a> </li>
<li>誊本：<a href="http://dancewithnet.com/snapshot/douglas-crockford-ajax-performance/">英文</a>、<a href="http://blog.360.yahoo.com/blog-sOW1QOA9crUyOdXFxOeK4xc-?cq=1&amp;p=200">中文</a> </li>
</ol>
</li>
<li>The JSON Saga
<ol>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockford-json">38 minutes</a> | <a href="http://yuiblog.com/yuitheater/crockford-json.m4v">M4V download</a> </li>
<li><a href="http://www.slideshare.net/kavenyan/the-json-saga">幻灯片</a></li>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockford-json">誊本</a></li>
</ol>
</li>
<li>
The State and Future of JavaScript</p>
<ol>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockford-yuiconf2009-state">55 minutes</a> | <a href="http://yuiblog.com/yuitheater/crockford-yuiconf2009-state.m4v">M4V download</a> </li>
<li><a href="http://www.yuiblog.com/assets/crockford-yuiconf2009-stateandfuture.ppt">幻灯片</a></li>
</ol>
</li>
<li><a href="http://yuiblog.com/crockford/">On JavaScript</a>
<ol>
<li>Volume One: The Early Years <sup>(Monday, January 25, 2010)</sup>
<ol>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-1">90 minutes</a> | <a href="http://yuiblog.com/yuitheater/crockonjs-1.m4v">M4V download</a> </li>
<li><a href="http://www.slideshare.net/douglascrockford/crockford-on-javascript-volume-one-the-early-years">幻灯片</a></li>
</ol>
</li>
<li>Chapter 2: And Then There Was JavaScript <sup>(Friday, February 5, 2010)</sup>
<ol>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-2">90 minutes</a> | <a href="http://yuiblog.com/yuitheater/crockonjs-2.m4v">M4V download</a> </li>
<li><a href="http://www.slideshare.net/douglascrockford/crockford-on-javascript-chapter-2-and-then-there-was-javascript">幻灯片</a></li>
</ol>
</li>
<li>Act III: Function the Ultimate <sup>(Wednesday, February 17, 2010)</sup>
<ol>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-3">73 minutes</a> | <a href="http://yuiblog.com/yuitheater/crockonjs-3.m4v">M4V download</a> </li>
<li><a href="http://www.slideshare.net/douglascrockford/crockford-on-javascript-act-iii-function-the-ultimate">幻灯片</a></li>
</ol>
</li>
<li>Episode IV: The Metamorphosis of Ajax <sup>(Wednesday, March 3, 2010)</sup>
<ol>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-4">93 minutes</a> | <a href="http://yuiblog.com/yuitheater/crockonjs-4.m4v">M4V download</a> </li>
<li><a href="http://www.slideshare.net/douglascrockford/crockford-on-javascript-episode-iv-the-metamorphosis-of-ajax">幻灯片</a></li>
</ol>
</li>
<li>Part 5: The End of All Things <sup>(Wednesday, March 31, 2010)</sup>
<ol>
<li><a href="http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-5">94 minutes</a> | <a href="http://yuiblog.com/yuitheater/crockonjs-5.m4v">M4V download</a> </li>
<li><a href="http://yuiblog.com/assets/crockonjs-5.pdf">幻灯片</a></li>
</ol>
</li>
</ol>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2009/03/29/douglas-crockford/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
<enclosure url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-2.m4v" length="139907805" type="video/x-m4v" />
<enclosure url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-1.m4v" length="139301206" type="video/x-m4v" />
<enclosure url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-3.m4v" length="135133974" type="video/x-m4v" />
<enclosure url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-tjpl-4.m4v" length="90013380" type="video/x-m4v" />
<enclosure url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-quality.m4v" length="192768058" type="video/x-m4v" />
<enclosure url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-goodstuff.m4v" length="172337121" type="video/x-m4v" />
<enclosure url="http://us.dl1.yimg.com/download.yahoo.com/dl/ydn/yui/theater/crockford-performance.m4v" length="195027943" type="video/x-m4v" />
		</item>
		<item>
		<title>JavaScript的陷阱</title>
		<link>http://dancewithnet.com/2008/10/27/javascript-gotchas/</link>
		<comments>http://dancewithnet.com/2008/10/27/javascript-gotchas/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 16:26:23 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[for]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[null]]></category>
		<category><![CDATA[parseInt]]></category>
		<category><![CDATA[String.replace()]]></category>
		<category><![CDATA[switch]]></category>
		<category><![CDATA[this]]></category>
		<category><![CDATA[undefined]]></category>
		<category><![CDATA[匿名函数]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1366</guid>
		<description><![CDATA[这本来是翻译Estelle Weyl的《15 JavaScript Gotchas》，里面介绍的都是在JavaScript编程实践中平时容易出错或需要注意的地方，并提供避开这些陷阱的方法，总体上讲，就是在认清事物本质的基础样要... ]]></description>
			<content:encoded><![CDATA[<p>这本来是翻译Estelle Weyl的<a href="http://www.evotech.net/blog/2008/10/13-javascript-gotchas/">《15 JavaScript Gotchas》</a>，里面介绍的都是在JavaScript编程实践中平时容易出错或需要注意的地方，并提供避开这些陷阱的方法，总体上讲，就是在认清事物本质的基础样要坚持好的编程习惯，其实这就是Douglas Crockford很久以前提出的JavaScript风格要素问题了，有些内容直接是相同的，具体请看<a href="http://dancewithnet.com/2008/01/26/the-elements-of-javascript-style-part-one/">《Javascript风格要素（1）》</a>和<a href="http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/">《Javascript风格要素（2）》</a>。在翻译的过程中，我又看到了贤安去年翻译的<a href="http://realazy.org/blog/2007/08/20/nine-javascript-gotchas/">《JavaScript的9个陷阱及评点》</a>，其内容又有些交叉在一起，所以我就在现有翻译的基础上做了一个简单的拼合，并依据自己的理解增加了一些注释和解释。<span id="more-1366"></span></p>
<ol>
<li><a href="#case-sensitivity">区分大小写：变量名、属性和方法全部都区分大小写</a></li>
<li><a href="#mismatching">不匹配的引号、圆括号或花括号将抛出错误</a></li>
<li><a href="#conditional-statements">条件语句：3个常见陷阱</a></li>
<li><a href="#line-breaks">换行：一直用分号结束语句来避免常见的换行问题</a></li>
<li><a href="#punctuation">标点法：在对象声明的尾部逗号将导致出错</a></li>
<li><a href="#html-id-conflicts">HTML id 冲突</a></li>
<li><a href="#variable-scope">变量作用域：全局变量对局部变量</a></li>
<li><a href="#function-overloading">函数重载：当重载不存在时，覆盖函数</a></li>
<li><a href="#string-replace">区分string.replace()函数不是全局的</a></li>
<li><a href="#parseInt">parseInt应该包含两个参数</a></li>
<li><a href="#this">“this”和绑定问题</a></li>
<li><a href="#default-param-value">为参数设置默认值，以免你遗漏它们</a></li>
<li><a href="#for-statements">for each循环是用于对象而不是数组</a></li>
<li><a href="#switch-statements">switch语句需要点技巧</a></li>
<li><a href="#undefined-vs-null">如果你要检查null，应该先检查undefined</a></li>
<li><a href="#event-handlers">时间处理陷阱</a></li>
</ol>
<h3 id="case-sensitivity">区分大小写</h3>
<p>变量名和函数名都是区分大小写的。就像配错的引号一样，这些大家都知道。但是，由于错误是不作声的，所以这是一个提醒。为自己选择一个命名规则，并坚持它。而且，记住JavaScript中的原生函数和CSS属性都是<a href="http://zh.wikipedia.org/wiki/驼峰式大小写">骆驼拼写法（camelCase）</a>。</p>
<pre><code>getElementBy<strong>Id</strong>(’myId’) != getElementBy<strong>ID</strong>(’myId’); <span>//它应该是“Id”而不是“ID”</span>
getElementById(’my<strong>Id</strong>‘) != getElementById(’my<strong>ID</strong>‘); <span>// “Id”也不等于“ID”</span>

document.getElementById('myId').style.<strong>Color</strong>; <span>//返回 "undefined"</span>
</code></pre>
<h3 id="mismatching">不匹配的引号、圆括号或花括号</h3>
<p>避免陷入不匹配的引号、圆括号或花括号陷阱的最好方式是编码时一直同时写出打开和关闭这两个元素符号，然后在其中间加入代码。开始：</p>
<pre><code>var myString = ""; <span>//在输入字符串值之前写入这对引号</span>
function myFunction(){
 if(){<span>//关闭每个打开的括弧</span>
 }
}
<span>//统计所有的左括号和右括号数量，并且确保它们相等</span>
alert(parseInt(var1)*(parseInt(var2)+parseInt(var3))); <span>//关闭每个打开的圆括号</span>
</code></pre>
<p>每当你打开一个元素，请关闭它。当你添加了关闭圆括号后，你再把函数的参数放进圆括号中。如果有一串圆括号，统计所有打开的圆括号和所有关闭的圆括号，并且确保这两个数字相等。</p>
<h3 id="conditional-statments">条件语句（3个陷阱）</h3>
<ol>
<li>所有的条件语句都必须位于圆括号中。<ins datetime="2008-10-28T18:05:25+80:00">执行语句主体不管是一句还是多句都强烈建议用花括号包围起来，这样能避免很多因修改或嵌套而产生的潜在错误。</ins>
<pre><code>if(var1 == var2){<span>//statement</span>}</code></pre>
</li>
<li>不要犯无意地使用赋值运算符的错误：把第二个参数的值赋给第一个参数。因为它是一个逻辑问题，它将一直返回true且不会报错。
<pre><code>if(var1 = var2){} <span>// 返回true。把var2赋值给var1</span></code></pre>
</li>
<li>JavaScript是弱类型，除了在<a href="http://www.evotech.net/blog/2007/07/javascript-switch-statement-quirks/">switch语句</a>中。当JavaScript在case比较时，它是非弱类型。
<pre><code>var myVar = 5;
if(myVar == '5'){ <span>//返回true，因为JavaScript是弱类型</span>
 alert("hi");  <span>//这个alert将执行，因为JavaScript通常不在意数据类型</span>
}
switch(myVar){
 case '5':
 alert("hi"); <span>//这个alert将不会执行，因为数据类型不匹配</span>
}
</code></pre>
</li>
</ol>
<h3 id="line-breaks">换行</h3>
<p>当心JavaScript中的硬换行。换行被解释为表示行结束的分号。即使在字符串中，如果在引号中包括了一个硬换行，那么你会得到一个解析错误（未结束的字符串）。</p>
<pre><code>var bad  = '&lt;ul id="myId"&gt;
  &lt;li&gt;some text&lt;/li&gt;
  &lt;li&gt;more text&lt;/li&gt;
  &lt;/ul&gt;'; <span>// 未结束的字符串错误</span>

var good = '&lt;ul id="myId"&gt;' +
 ‘&lt;li&gt;some text&lt;/li&gt;‘ +
 ‘&lt;li&gt;more text&lt;/li&gt;‘ +
 ‘&lt;/ul&gt;’; <span>// 正确</span>
</code></pre>
<p>前面讨论过的换行被解释为分号的规则并不适用于控制结构这种情况：条件语句关闭圆括号后的换行并不是给其一个分号。</p>
<p>一直使用分号和圆括号，那么你不会因换行而出错，你的代码易于阅读，且除了那些不使用分号的怪异源码外你会少一些顾虑：所以当移动代码且最终导致两个语句在一行时，你无需担心第一个语句是否正确结束。</p>
<h3 id="punctuation">多余的逗号</h3>
<p>在任何JavaScript对象定义中，最后一个属性决不能以一个逗号结尾。Firefox不会出错，而IE会报语法错误。</p>
<pre><code>var theObj = {
        city : "Boston",
        state : "MA",<span>//IE6和IE7中有“缺少标识符、字符串或数字”的错误，IE8 beta2修正了它</span>
  }</code></pre>
<h3 id="html-id-conflicts">HTML id 冲突</h3>
<p><a href="http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html">JavaScript DOM绑定（JavaScript DOM bindings）</a>允许通过HTML id索引。在JavaScript中函数和属性共享同一个名字空间。所以，当在HTML中的一个id和函数或属性有相同的名字时，你会得到难以跟踪的逻辑错误。然而这更多是一个<a href="http://www.evotech.net/blog/2007/04/css-best-practices/">CSS最佳实践</a>的问题，当你不能解决你的JavaScript问题时，想起它是很重要的。</p>
<pre><code>
&lt;ul&gt;
&lt;li id="length"&gt;1&lt;/li&gt;
&lt;li id="thisLength"&gt;2&lt;/li&gt;
&lt;li id="thatLength"&gt;3&lt;/li&gt;
&lt;/ul&gt;
&lt;script&gt;
var listitems = document.getElementsByTagName('li');
var liCount = listitems.length; <span>//IE下返回的是&lt;li id="length"&gt;1&lt;/li&gt;这个节点而不是所有&lt;li的数量</span>

var thisLength = document.getElementById('thisLength');
    thatLength = document.getElementById('thatLength');
    <span>//IE下会出现“对象不支持此属性和方法”的错误，IE8 beta2下首次加载页面会出错，刷新页面则不会</span>
    <span>//在IE中thisLength和thatLength直接表示以其为id值的DOM节点，</span>
    <span>//所以赋值时会出错，当有var声明时，IE会把其当着变量，这个时候就正常了。</span>
&lt;/script&gt;
</code></pre>
<p> 如果你要标记(X)HTML，绝不要使用JavaScript方法或属性名作为id的值。并且，当你写JavaScript时，避免使用 (X)HTML中的id值作为变量名。</p>
<h3 id="variable-scope">变量作用域</h3>
<p>JavaScript中的许多问题都来自于变量作用域：要么认为局部变量是全局的，要么用函数中的局部变量覆盖了全局变量。为了避免这些问题，最佳方案是根本没有任何全局变量。但是，如果你有一堆，那么你应该知道这些陷阱。</p>
<p>不用var关键字声明的变量是全局的。记住使用var关键字声明变量，防止变量具有全局作用域。在下面例子中，在函数中声明的变量具有全局变量，因为没有使用var关键字声明：</p>
<pre><code>anonymousFuntion1 = function(){
 globalvar = 'global scope'; <span>//全局声明，因为“var”遗漏了</span>
 return localvar;
}();
alert(globalvar); <span>//弹出“global scope”，因为函数中的变量是全局声明</span>

anonymousFuntion2 = function(){
 var localvar = 'local scope'; <span>//使用“var”局部声明</span>
 return localvar;
}();
alert(localvar); <span>//错误 “localvar未定义”。没有全局定义localvar</span>
</code></pre>
<p>作为参数引进到函数的变量名是局部的。如果参数名也是一个全局变量的名字，像参数变量一样有局部作用域，这没有冲突。如果你想在函数中改变一个全局变量，这个函数有一个参数复制于这个全局变量名，记住所有全局变脸都是window对象的属性。</p>
<pre><code>var myscope = "global";
function showScope(myscope){
 return myscope; <span>//局部作用域，即使有一个相同名字的全局变量</span>
}
alert(showScope('local'));

function globalScope(myscope){
 myscope = <strong>window.myscope</strong>; <span>//全局作用域</span>
 return myscope;
}
alert(globalScope(’local’));
</code></pre>
<p>你甚至可以在循环中声明变量：</p>
<pre><code>for(var i = 0; i < myarray.length; i++){}</code></code></pre>
<h3 id="function-overloading">覆盖函数/重载函数</h3>
<p>当你不止一次的声明一个函数时，这个函数的最后一次声明将覆盖掉该函数的所有前面版本且不会抛出任何错误或警告。这不同于其他的编程语言，像Java，你能用相同的名字有多重函数，只要它们有不同的参数：调用函数重载。在JavaScript中没有重载。这使得不能在代码中使用JavaScript核心部分的名字极其重要。也要当心包含的多个JavaScript文件，像一个包含的脚本文件可能覆盖另一个脚本文件中的函数。请使用匿名函数和名字空间。</p>
<pre><code>(function(){
 <span>// creation of my namespace 创建我的名字空间</span>
 if(!window.MYNAMESPACE) {
  window['MYNAMESPACE'] = {};
 }
 <span>//如果名字空间不存在，就创建它</span>
 <span>//这个函数仅能在匿名函数中访问</span>
 function myFunction(var1, var2){
  <span>//内部的函数代码在这儿</span>
 }
 <span>// 把内部函数连接到名字空间上，使它通过使用名字空间能访问匿名函数的外面 </span>
 window['MYNAMESPACE']['myFunction'] = myFunction;
})(); <span>// 圆括号 = 立即执行</span>
<span>// 包含所有代码的圆括号使函数匿名</span>
</code></pre>
<p>这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看<a href="http://dancewithnet.com/2008/05/07/javascript-anonymous-function/">《Javascript的匿名函数》</a>。<a href="http://developer.yahoo.com/yui/">YUI</a>整个库只有YAHOO和YAHOO_config两个全局变量，它正是大量应用匿名函数和命名空间的方法来实现，具体请看<a href="http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/">《Javascript的一种模块模式》</a>。</p>
<h3 id="string-replace">字符串替换</h3>
<p>一个常见错误是假设字符串替换方法的行为会对所有可能匹配都产生影响。实际上，JavaScript字符串替换只改变了第一次发生的地方。为了替换所有发生的地方，你需要设置全局标识。同时需要记住String.replace()的第一个参数是一个正则表达式。</p>
<pre><code>var myString = "this is my string";
myString = myString.replace("","%20"); // "this%20is my string"
myString = myString.replace(/ /,"%20"); // "this%20is my string"
myString = myString.replace(/ /g,"%20"); // "this%20is%20my%20string"
</code></pre>
<h3 id="parseInt">parseInt</h3>
<p>在JavaScript得到整数的最常见错误是假设parseInt返回的整数是基于10进制的。别忘记第二个参数基数，它能是从2到36之间的任何值。为了确保你不会弄错，请一直包含第二个参数。</p>
<pre><code>parseInt('09/10/08'); <span>//0</span>
parseInt(’09/10/08′,10); <span>//9, 它最可能是你想从一个日期中得到的值</span>
</code></pre>
<p>如果parseInt没有提供第二个参数，则前缀为 &#8216;0x&#8217; 的字符串被当作十六进制，前缀为 &#8216;0&#8242; 的字符串被当作八进制。所有其它字符串都被当作是十进制的。如果 numString 的前缀不能解释为整数，则返回 NaN（而不是数字）。</p>
<h3 id="this">‘this’</h3>
<p>另一个常见的错误是忘记使用“this”。在JavaScript对象中定义的函数访问这个对象的属性，但没有使用引用标识符“this”。例如，下面是错误的：</p>
<pre><code>function myFunction() {
 var myObject = {
  objProperty: "some text",
  objMethod: function() {
   alert(objProperty);
  }
 };
 myObject.objMethod();
} 

function myFunction() {
 var myObject = {
  objProperty: "some text",
  objMethod: function() {
   alert(this.objProperty);
  }
 };
 myObject.objMethod();
}
</code></pre>
<p>有一篇<a href="http://www.alistapart.com/articles/getoutbindingsituations">A List Apart文章</a>用通俗易懂的英文表达了this绑定的问题。</p>
<p>对this使用最大的陷阱是this在使用过程中其引用会发生改变：</p>
<pre><code>&lt;input type="button" value="Gotcha!" id="MyButton"&gt;
&lt;script&gt;
var MyObject = function () {
    this.alertMessage = "Javascript rules";
    this.ClickHandler = function() {
        <strong>alert(this.alertMessage );</strong>
        <span>//返回结果不是”JavaScript rules”，执行MyObject.ClickHandler时，</span>
        <span>//this的引用实际上指向的是document.getElementById("theText")的引用</span>
  }
}();
document.getElementById(”theText”).onclick =  MyObject.ClickHandler
&lt;/script&gt;
</code></pre>
<p>其解决方案是：</p>
<pre><code>
var MyObject = function () {
    <strong>var self = this;</strong>
    this.alertMessage = “Javascript rules”;
    this.OnClick = function() {
        alert(self.value);
    }
}();
</code></pre>
<p>类似问题的更多细节和解决方案请看<a href="http://realazy.org/blog/2007/07/18/scope-in-javascript/">《JavaScript作用域的问题》</a>。</p>
<h3 id="default-param-value">遗漏的参数</h3>
<p>当给函数增加一个参数时，一个常见的错误是忘记更新这个函数的所有调用。如果你需要在已经被调用的函数中增加一个参数来处理一个特殊情况下的调用，请给这个函数中的这个参数设置默认值，以防万一在众多脚本中的众多调用中的一个忘记更新。</p>
<pre><code>function addressFunction(address, city, state, country){
 <strong>country = country || “US”</strong>; <span>//如果没有传入country,假设 “US”</span>
 span>//剩下代码
}
</code></pre>
<p>你也能通过获取arguments来解决。但是在这篇文章我们的注意力在陷阱上。同时在<a href="http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/">《Javascript风格要素（2）》</a>也介绍了||巧妙应用。</p>
<h3 id="for-statements">for关键字</h3>
<p>在JavaScript中关键字for有两种使用方式，一个是for语句，一个是for/in语句。for/in语句将遍历所有的对象属性（attribute），包括方法和属性（property）。决不能使用for/in来遍历数组：仅在当需要遍历对象属性和方法时才使用for/in。</p>
<ol>
<li>for(var myVar in myObject)语句用一个指定变量无任何规律地遍历对象的所有属性。如果for/in循环的主体删除了一个还没有枚举出的属性，那么该属性就不在枚举。如果循环主体定义了新属性，那么循环是否枚举该属性则是由JavaScript的实现决定。</li>
<li>for(var 1=0; i < myArray.length; i++)语句会遍历完一个数组的所有元素。</li>
</li>
</ol>
<p>为了解决这个问题，大体上你可以对对象使用 for &#8230; in，对数组使用for循环：</p>
<pre><code>listItems = document.getElementsByTagName('li');
for (var listitem in listItems){
 <span>//这里将遍历这个对象的所有属性和方法，包括原生的方法和属性，但不遍历这个数组：出错了！</span>
}
<span>//因为你要循环的是数组对象，所用for循环</span>
for ( var i = 0; i < listItems.length; i++) {
 <span>//这是真正你想要的
}
</code></pre>
<p>对象的有些属性以相同的方式标记成只读的、永久的或不可列举的，这些属性for/in无法枚举。实际上，for/in循环<br />
会遍历所有对象的所有可能属性，包括函数和原型中的属性。所有修改原型属性可能对for/in循环带来致命的危害，所以需要采用hasOwnProperty和typeof做一些必要的过滤，最好是用for来代替for/in。</p>
<h3 id="switch-statements">switch语句</h3>
<p>Estelle Weyl写了一篇<a href="http://www.evotech.net/blog/2007/07/javascript-switch-statement-quirks/">switch statement quirks</a>，其要点是：</p>
<ol>
<li>没有数据类型转换</li>
<li>一个匹配，所有的表达式都将执行直到后面的break或return语句执行</li>
<li>你可以对一个单独语句块使用多个case从句</li>
</ol>
<h3 id="undefined-vs-null">undefined ≠ null</h3>
<p>null是一个对象，undefined是一个属性、方法或变量。存在null是因为对象被定义。如果对象没有被定义，而测试它是否是null，但因为没有被定义，它无法测试到，而且会抛出错误。</p>
<pre><code>if(myObject !== null  &#038;&#038; typeof(myObject) !== 'undefined') {
 <span>//如果myObject是undefined，它不能测试是否为null，而且还会抛出错误</span>
}
if(typeof(myObject) !== 'undefined' &#038;&#038; myObject !== null) {
 <span>//处理myObject的代码</span>
}
</code></pre>
<p><a href="http://blog.poundbang.in/post/30056940/javascript-gotcha-undefined-vs-null">Harish Mallipeddi</a>对undefined和null有一个说明。</p>
<h3 id="event-handlers">事件处理陷阱</h3>
<p>刚接触事件处理时最常见的写法就是类似：</p>
<pre><code>window.onclick = MyOnClickMethod</code></pre>
<p>这种做法不仅非常容易出现后面的window.onclick事件覆盖掉前面的事件，还可能导致大名顶顶的IE内存泄露问题。为了解决类似问题，4年前<a href="http://simon.incutio.com/archive/2004/05/26/addLoadEvent">Simon Willison</a>就写出了很流行的addLoadEvent()：</p>
<pre><code>function addLoadEvent(func) {
 var oldonload = window.onload;
 if (typeof window.onload != 'function') {
  window.onload = func;
 }else {
  window.onload = function() {
   oldonload();
   unc();
  }
 }
}
addEvent(window,'load',func1,false);
addEvent(window,'load',func2,false);
addEvent(window,'load',func3,false);
</code></pre>
<p>当然在JavaScript库盛行的现在，使用封装好的事件处理机制是一个很好的选择，比如在YUI中就可以这样写：</p>
<pre><code>YAHOO.util.Event.addListener(window, "click", MyOnClickMethod);</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/10/27/javascript-gotchas/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Javascript的匿名函数</title>
		<link>http://dancewithnet.com/2008/05/07/javascript-anonymous-function/</link>
		<comments>http://dancewithnet.com/2008/05/07/javascript-anonymous-function/#comments</comments>
		<pubDate>Tue, 06 May 2008 17:14:40 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[函数]]></category>
		<category><![CDATA[匿名函数]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1297</guid>
		<description><![CDATA[一、什么是匿名函数？
在Javascript定义一个函数一般有如下三种方式：

函数关键字(function)语句：
function fnMethodName(x){alert(x);}

函数字面量(Function Literals)：
var fnMethodName = function(x){alert(x);}

Functio... ]]></description>
			<content:encoded><![CDATA[<h3>一、什么是匿名函数？</h3>
<p>在Javascript定义一个函数一般有如下三种方式：</p>
<ol>
<li><strong>函数关键字(function)语句</strong>：
<pre><code>function fnMethodName(x){alert(x);}</code></pre>
</li>
<li><strong>函数字面量(Function Literals)</strong>：
<pre><code>var fnMethodName = function(x){alert(x);}</code></pre>
</li>
<li><strong>Function()构造函数</strong>：
<pre><code>var fnMethodName = new Function('x','alert(x);')</code></pre>
</li>
</ol>
<p>上面三种方法定义了同一个方法函数fnMethodName，第1种就是最常用的方法，后两种都是把一个函数复制给变量fnMethodName，而这个函数是没有名字的，即匿名函数。实际上，<a href="http://en.wikipedia.org/wiki/Anonymous_function">相当多的语言都有匿名函数</a>。<span id="more-1297"></span></p>
<h3>二、函数字面量和Function()构造函数的区别</h3>
<ol>
<li>虽然函数字面量是一个匿名函数，但语法允许为其指定任意一个函数名，当写递归函数时可以调用它自己，使用Function()构造函数则不行。
<pre><code>var f = function fact(x) {
  if (x < = 1) return 1;
  else return x*fact(x-1);
};</code></code></pre>
</li>
<li>Function()构造函数允许运行时Javascript代码动态的创建和编译。在这个方式上它类似全局函数eval()。</li>
<li>Function()构造函数每次执行时都解析函数主体，并创建一个新的函数对象。所以当在一个循环或者频繁执行的函数中调用Function()构造函数的效率是非常低的。相反，函数字面量却不是每次遇到都重新编译的。</li>
<li>用Function()构造函数创建一个函数时并不遵循典型的作用域，它一直把它当作是顶级函数来执行。
<pre><code>var y = "global";
function constructFunction() {
    var y = "local";
    return new Function("return y");  <span>//  无法获取局部变量</span>
}
alert(constructFunction()());  <span>// 输出 "global"</span>
</code></pre>
</li>
</ol>
<p>和函数关键字定义相比Function()构造器有自己的特点且要难以使用的多，所以这项技术通常很少使用。而函数字面量表达式和函数关键字定义非常接近。考虑前面的区别，虽然有消息说字面量的匿名函数在OS X 10.4.3下的某些webkit的引擎下有bug，但我们平常所说的匿名函数均指采用函数字面量形式的匿名函数。更多详细内容可以阅读《JavaScript: The Definitive Guide, 5th Edition》的Functions那章。</p>
<h3>三、匿名函数的代码模式</h3>
<p>昨天<a href="http://www.hedgerwow.com">hedger wang</a>在他的blog介绍了<a href="http://www.hedgerwow.com/360/dhtml/js-anonymous-function-patterns.html">几种匿名函数的代码模式</a>：</p>
<p><strong>错误模式</strong>：其无法工作，浏览器会报语法错。</p>
<pre><code>function(){
  alert(1);
}();</code></pre>
<ol>
<li><strong>函数字面量</strong>：首先声明一个函数对象，然后执行它。
<pre><code>(function(){
  alert(1);
} ) ( );</code></pre>
</li>
<li><strong>优先表达式</strong>：由于Javascript执行表达式是从圆括号里面到外面，所以可以用圆括号强制执行声明的函数。
<pre><code>( function(){
  alert(2);
} ( ) );</code></pre>
</li>
<li><strong>Void操作符</strong>：用void操作符去执行一个没有用圆括号包围的一个单独操作数。
<pre><code>void function(){
  alert(3);
}()</code></pre>
</li>
</ol>
<p>这三种方式是等同的，hedger wang因为个人原因比较喜欢第3种，而在实际应用中我看到的和使用的都是第1种。</p>
<h3>四、匿名函数的应用</h3>
<ol>
<li><a href="http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/">《Javascript的一种模块模式》</a>中的第一句话就是“全局变量是魔鬼”。配合var关键字，匿名函数可以有效的保证在页面上写入Javascript，而不会造成全局变量的污染。这在给一个不是很熟悉的页面增加Javascript时非常有效，也很优美。实际上，<a href="http://developer.yahoo.com/yui/">YUI</a>以及其相应的范例中大量使用匿名函数，其他的Javascript库中也不乏大量使用。</li>
<li>Javascript的函数式编程(functional programming)的基石。具体请看<a href="http://www.ibm.com/developerworks/cn/web/wa-javascript.html">《用函数式编程技术编写优美的 JavaScript》</a>和<a href="http://shiningray.cn/functional_javascript_programming.html">《函数式JavaScript编程指南》</a>。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/05/07/javascript-anonymous-function/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
		<item>
		<title>Javascript风格要素（2）</title>
		<link>http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/</link>
		<comments>http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 11:28:15 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/</guid>
		<description><![CDATA[我们使用习惯用法可以使我们的意图更加的清晰和简洁。
使用==时，当心强制转换
考虑下面函数：
function gw(f) {
 if (d.w.sv.checked == true) {
  zv = 'on';
 } else {
  zv = 'off';
 }
 procframe.location.replace("http:/... ]]></description>
			<content:encoded><![CDATA[<p>我们使用习惯用法可以使我们的意图更加的清晰和简洁。</p>
<h3>使用<code>==</code>时，当心强制转换</h3>
<p>考虑下面函数：</p>
<pre><code>function gw(f) {
 if (d.w.sv.checked == true) {
  zv = 'on';
 } else {
  zv = 'off';
 }
 procframe.location.replace("http://b.www.yahoo.com/module/wtr_tr.php?p=" +
 escape(f.p.value) + "&#038;sv=" + zv);
 return false;
}</code></pre>
<p><span id="more-1235"></span></p>
<p>==运算符不应该被用着和true比较值，因为它要执行强制转换。如果我们想确定<code>d.w.sv.checked</code>是否是布尔值<br /><code>true</code>，我们必须用<code>===</code>运算符。如果我们仅在意一个值是真实存在的不是假的，最好不要用相等运算符。</p>
<p>例如，由于强制转换：<code>1 == true</code>是真，<code>1 === true</code>是假。<code>==</code>运算符隐藏了类型错误。</p>
<h3>使用?:运算符选择两值之一</h3>
<p>if语句通常被用来从两个值中选择一个。这应该是三元操作符<code>?:</code>最适合的。</p>
<pre><code>zv = d.w.sv.checked ? 'on' : 'off';</code></pre>
<h3>绝不使用隐含的全局变量</h3>
<p>变量<code>zv</code>不是作为一个<code>var</code>或函数参数来声明的，所以它是一个隐式的全局变量。如果这个页面的另一个函数使用了同样名字的全局变量，则可能得到一个失败的结果。这样的臭虫（bug）是非常难以发现，却很容易避免。这个例子中，我们既可以声明<code>zv</code>为一个<code>var</code>，也可以发现它仅仅被使用过一次而整个去掉它。</p>
<pre><code>function gw(f) {
 procframe.location.replace("http://b.www.yahoo.com/module/wtr_tr.php?p=" +
 escape(f.p.value) + "&#038;sv=" + d.w.sv.checked ? 'on' : 'off');
 return false;
}</code></pre>
<h3>绝不使用?:运算符选择两种行为之一 </h3>
<p>我们常质疑那些返回一个常量的函数，但这有时是在浏览器环境下所必需的。</p>
<p>下面我们看一个不正确使用<code>?:</code>运算符的例子。它常被用于在两个任务间选择。</p>
<pre><code>function u(o, z) {
 var em = o.id.substring(1);
 var p = d.getElementById('e' + em);
 if (p) {
  (z == 0) ? p.style.backgroundColor = '#fff' :
  p.style.backgroundColor = '#989898';
 }
 p = d.getElementById('e' + (em - 1));
 if (p) {
  (z == 0) ? p.style.backgroundColor = '#fff' :
  p.style.backgroundColor = '#989898';
 }
}</code></pre>
<p>对<code>Z</code>的判断是模糊不清的。<code>Z</code>正好等于<code>0</code>时我们选择<code>#fff</code>颜色，那么，<code>Z</code>不等于时？如上所述似乎指明的是前者，但它实际上是后者。在这个例子中幸运的是，我们大概想要的就是后者，所以它不是技术上错误（这次）。但是在文体上只糟糕的。</p>
<p>我们可以用<code>if</code>代替<code>?:</code>，但碰巧的是这些值对应的是同一个左值(lvalue)，所以我们无需<code>if</code>就可以改正这个错误。</p>
<pre><code>function u(o, z) {
 var em = o.id.substring(1),
 p = d.getElementById('e' + em);
 if (p) {
  p.style.backgroundColor = z ? '#fff' : '#989898';
 }
 p = d.getElementById('e' + (em - 1));
 if (p) {
  p.style.backgroundColor = z ? '#fff' : '#989898';
 }
}</code></pre>
<h3>使用||运算符指定一个默认值</h3>
<p>事件处理程序依赖于浏览器。理想情况下，应用程序应该通过公共库隔绝对浏览器的依赖。当没有这样的库时，就会有些函数发生如下情况：</p>
<pre><code>function md(e) {
 (window.event) ? ev = window.event : ev = e;
 (ev.target) ? sr = ev.target : sr = ev.srcElement;
 if (ev &#038;&#038; sr &#038;&#038; sr.id == "fp" || sr.id == "sb") st = 1;
 if (sr.className.indexOf("pllist") &lt; 0 &#038;&#038; sr.className != "more" &#038;&#038;
  sr.className != "plinkc" &#038;&#038; sr.tagName != "scrollbar " &#038;&#038;
  _toClose &#038;&#038; _toCloseNorgie) {
  d.getElementById(_toClose).innerHTML = "";
  _toClose = "";
  _toCloseNorgie.parentNode.className = '';
  _toCloseNorgie = '';
 }
}</code></pre>
<p>一些浏览器把事件对象作为一个参数传给事件管理程序。微软选用把事件对象放入到一个全局的事件变量中。在Javascript中，全局变量是全局对象的成员。在浏览器中，全局对象始终包含一个<code>window</code>对象成员，其值是全局对象。当测试一个变量是否存在时，通过<code>window</code>访问全局变量是避免未定义变量错误的一种方法。无论如何，做这样的测试不应该是必要的。</p>
<p>我们能通过问它是否是另外一种，来代替首先判断是否是微软事件。</p>
<pre><code>ev = e || event;</code></pre>
<p>我们用<code>||</code>(默认)运算符。如果<code>e</code>是真，我们将有它的值，但是如果<code>e</code>是假，则我们将用<code>event</code>。</p>
<p>在下一个语句，我们又用<code>||</code>运算符去确定<code>sr</code>是哪个值。</p>
<p>我们应该用<code>var</code>去声明<code>ev</code>和<code>sr</code>来避免全局冲突：</p>
<pre><code>function md(e) {
 var ev = e || event,
  sr = ev.target || ev.srcElement;
 if (sr &#038;&#038; (sr.id == 'fp' || sr.id == 'sb')) {
  st = 1;
 }
 if (sr.className.indexOf('pllist') < 0 &#038;&#038; sr.className != 'more' &#038;&#038;
 sr.className != 'plinkc' &#038;&#038; sr.tagName != 'scrollbar ' &#038;&#038;
 _toClose &#038;&#038; _toCloseNorgie) {
  d.getElementById(_toClose).innerHTML = '';
  _toClose = '';
  _toCloseNorgie.parentNode.className = '';
  _toCloseNorgie = '';
 }
}</code></code></pre>
<h3>全局变量是魔鬼</h3>
<p>下面我们看到另一个时间处理程序。正如你所料，它重复像前面一样破坏风格。</p>
<pre><code>function kd(e) {
 (window.event) ? ev = window.event : ev = e;
 (ev.target) ? el = ev.target : el = ev.srcElement;
 if (ev &#038;&#038; el) {
  code = ev.keyCode;
  id = el.id;
 } else {
  return;
 }
 ctn = lt.id.substring(1);
 if (code == 13) {
  return;
 } else if ((code == 191 || code == 222) &#038;&#038; id != 'fp') {
  _ffs = 1;
  gk = 0;
 } else if ((code &lt; 31 || code &gt; 41) &#038;&#038;
 (code &lt; 16 || code &gt; 18) &#038;&#038; code != 9 &#038;&#038; code != 8 ) {
  gk = 1;
 } else {
  gk = 0;
 }
 if (!_ffs &#038;&#038; (id == 'fp' || id == 'st')) {
  if (code == 9) {
   if (box.value == '' || (box.value != '' &#038;&#038; (at == 1 || ev.shiftKey))) {
    mt(ctn);
   } else if (id == 'st' &#038;&#038; box.value != '' &#038;&#038; at == 0) {
    at = 1;
    mt(ctn);
   }
  } else if (id == 'fp' &#038;&#038; gk == 0 &#038;&#038;  (box.value == '' &#038;&#038; st == 0)
    &#038;&#038; !ev.shiftKey &#038;&#038; !ev.ctrlKey &#038;&#038; !ev.altKey) {
    d.getElementById('mk').focus();
    d.getElementById('mk').blur();
  } else if (gk == 1) {
  at = 0;
 }
 } else if ((id == 'mk2' &#038;&#038; box.value != '' &#038;&#038; ev.shiftKey &#038;&#038; code == 9) ||
   (id == 'm6' &#038;&#038; !ev.shiftKey &#038;&#038; code == 9)){
    d.getElementById('mk').focus();
   } else if (!_ffs &#038;&#038; gk == 1 &#038;&#038; el.type != 'text' &#038;&#038; !ev.ctrlKey &#038;&#038; !ev.altKey){
    box.value = '';
    box.focus();
  }
}
function mt(ctn) {
 if ((ev &#038;&#038; !ev.ctrlKey &#038;&#038; !ev.altKey) || !ev) {
  if (ev.shiftKey){
   nextTab = parseInt(ctn) - 1;
  } else {
   nextTab = parseInt(ctn) + 1;
  }
  if (nextTab == 0) {
   d.getElementById('mk').focus();
  } else if (nextTab &lt; 8 ) {
   t(d.getElementById('v' + nextTab));
  } else {
   return;
  }
 }
}</code></pre>
<p>有意思的是它有一个同伴函数<code>mt</code>，它仅被<code>kd</code>调用。<code>mt</code>被传给一个参数<code>ctn</code>，但<code>kd</code>和<code>mt</code>之间的通讯大部分是通过全局变量。</p>
<h3>使用内部函数避免全局变量</h3>
<p>我们可以通过增加传递给<code>mt</code>的参数数量来除掉所有的全局变量。但代替方案，我们将使<code>mt</code>变成<code>kd</code>的内部函数。作为一个内部函数，<code>mt</code>能访问<code>kd</code>的所有变量。</p>
<pre><code>unction kd(e) {
    var ev = e || event,
        el = ev.target || ev.srcElement,
        cnt,
        code = ev.keyCode,
        gk,
        id = el.id,
        ctn = lt.id.substring(1);

    function mt() {
        var nextTab;
        if (!ev.ctrlKey &#038;&#038; !ev.altKey) {
            nextTab = parseInt(ctn) + ev.shiftKey ? -1 : 1;
            if (!nextTab) {
                d.getElementById('mk').focus();
            } else if (nextTab &lt; 8 ) {
                t(d.getElementById('v' + nextTab));
            }
        }
    }

    if (code == 13) {
        return;
    } else if ((code == 191 || code == 222) &#038;&#038; id != 'fp') {
        _ffs = 1;
        gk = 0;
    } else if ((code &lt; 31 || code &gt; 41) &#038;&#038;
            (code &lt; 16 || code &gt; 18) &#038;&#038; code != 9 &#038;&#038; code != 8 ) {
        gk = 1;
    } else {
        gk = 0;
    }
    if (!_ffs &#038;&#038; (id == 'fp' || id == 'st')) {
        if (code == 9) {
            if (box.value == '' ||
                    (box.value != '' &#038;&#038; (at == 1 || ev.shiftKey))) {
                mt();
            } else if (id == 'st' &#038;&#038; box.value != '' &#038;&#038; at == 0) {
                at = 1;
                mt();
            }
        } else if (id == 'fp' &#038;&#038; gk == 0 &#038;&#038; (box.value == '' &#038;&#038; st == 0) &#038;&#038;
                !ev.shiftKey &#038;&#038; !ev.ctrlKey &#038;&#038; !ev.altKey) {
            d.getElementById('mk').focus();
            d.getElementById('mk').blur();
        } else if (gk == 1) {
            at = 0;
        }
    } else if ((id == 'mk2' &#038;&#038; box.value != '' &#038;&#038; ev.shiftKey &#038;&#038; code == 9) ||
            (id == 'm6' &#038;&#038; !ev.shiftKey &#038;&#038; code == 9)){
        d.getElementById('mk').focus();
    } else if (!_ffs &#038;&#038; gk == 1 &#038;&#038; el.type != 'text' &#038;&#038; !ev.ctrlKey &#038;&#038;
            !ev.altKey) {
        box.value = '';
        box.focus();
    }
}</code></pre>
<p>在函数<code>kd</code>中，从两个地方调用函数<code>mt</code>。通过使它成为一个内部函数，我们能有效的减少<code>kd</code>所用到的全局变量的数目，这将降低了干扰其他组件的可能性。<code>kd</code>依旧是一个烂摊子，但它现在不是一无是处的烂摊子。</p>
<p>原文：<a href="http://www.crockford.com/">Douglas Crockford</a>的<a href="http://javascript.crockford.com/style2.html">The Elements of JavaScript Style Part Two: Idioms</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Javascript风格要素（1）</title>
		<link>http://dancewithnet.com/2008/01/26/the-elements-of-javascript-style-part-one/</link>
		<comments>http://dancewithnet.com/2008/01/26/the-elements-of-javascript-style-part-one/#comments</comments>
		<pubDate>Sat, 26 Jan 2008 09:03:48 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2008/01/26/the-elements-of-javascript-style-part-one/</guid>
		<description><![CDATA[程序设计是困难的，其核心是管理的复杂性。计算机程序是人类做出的最复杂的东西。质量是不可靠的且隐蔽的。
好的体系架构是必需给程序足够的结构使其健壮而不会陷入混乱的泥淖，但我... ]]></description>
			<content:encoded><![CDATA[<p>程序设计是困难的，其核心是管理的复杂性。计算机程序是人类做出的最复杂的东西。质量是不可靠的且隐蔽的。</p>
<p>好的体系架构是必需给程序足够的结构使其健壮而不会陷入混乱的泥淖，但我们表达一个程序细节的方式是同等重要的。一个程序的本质会被不良的编码所隐藏。只有当一个程序的表达清晰时，我们才能有希望正确的推理出它的效率、安全和正确性。</p>
<p>William Strunk的<a href="http://crockford.com/wrrrld/style.html">《风格要素》(The Elements of Style)</a>是关于文学风格的经典著作，它是一本关于英文写作的薄手册，在用法、组织和形式上提出忠告。风格的理念应用于编程，在1972年Kreitzberg和Shneiderman的<a href="http://www.amazon.com/exec/obidos/ASIN/0155221566/wrrrldwideweb">《FORTRAN风格要素》（The Elements of FORTRAN Style）</a>中是不成功的，但在1978年的Kernighan和Plauger的<a href="http://www.amazon.com/exec/obidos/ASIN/0070342075/wrrrldwideweb">《编程风格要素》（The Elements of Programming Style）</a>中是非常成功的：<span id="more-1234"></span></p>
<blockquote><p>好的编程不能通过笼统的说教。学习编程的好方法是一次又一次的思考：真正的编程是如何通过一些良好实践的原则和一点常识来进行改进的。</p>
</blockquote>
<p>他们从他们批评和改进的其他的编程教科书中筛选程序。</p>
<p>当我们在这里谈论风格时，我们谈论的不是潮流或者时尚，也不是CSS、布局惯例或排版。我们正在谈论的是能真正提高代码价值的表达式的永恒品质。对于公司来说，他们的评估和他们的代码是息息相关的，风格应该是一个至关重要的受关注内容。</p>
<p>我们使用许多编程语言，但在某一方面，Javascript是最重要的，它是浏览器的语言。当人们访问我们的站点时，他们将邀请我们的Javascript程序在他们的机器中执行。我们有义务使那些程序执行好。</p>
<p>没有好的关于Javascript编程的课本。在网页使用Javascript的大多数人学习它是通过从糟糕的书、糟糕的站点和糟糕的工具中复制相当糟糕的例子。我们这里有极好的Javascript程序员社区，但我们依旧能从较好的风格实践中获益。</p>
<p>为了证明这个问题，我将从公共网站中抽取一些程序，展示它们如何能被改进。这并不是我有意为难任何人。我的意图仅是通过例子展示风格的价值。我不会保留任何秘密：我展示给你的是我们已经传送给世界上的每一个人。</p>
<h3>淘汰过时结构</h3>
<p>下面的例子是2005-09-19摘自<a href="www.yahoo.com">www.yahoo.com</a>：</p>
<pre><code>&lt;script language=javascript&gt;&lt;!--
     lck='',
     sss=1127143538,
     ylp='p.gif?t=1127143538&amp;_ylp=A0Je5ipy2C5D54AAwVX1cSkA',
     _lcs='';
--&gt;&lt;/script&gt; </code></pre>
<p>这个脚本块用了language属性。这个特性是微软为了支持VBScript引入的。然而Netscape采用它是为了支持非标准偏差。W3C不采取这个language属性，倾向使用MIME类型的type属性取代。不幸的是，MIME类型未得到标准化，所以它有时是&#8221;text/javascript&#8221;、&#8221;application/ecmascript&#8221;或其他。幸运的是所有的浏览器都选择Javascript作为默认的编程语言，所以简单的写&lt;script&gt;是最好的。它最小，且工作在最多的浏览器。在脚本中使用HTML的注释的时间要回溯到Netscape Navigator和Netscape Navigator 2的兼容问题上来。后者引入了&lt;script&gt;标签。然而，前者的用户能像文本一样看到脚本，因为在HTML惯例中不能识别的标签被忽略。&lt;!&#8211;注释hack在Netscape Navigator 3出现的时候是需要的，现在它不被需要了。它是丑陋的且浪费空间的。</p>
<p>逗号运算符像Javascript语法的大多数一样从C语言中借用。逗号运算符获得两个值，且返回第二个。在语言的定义中它的存在易于掩盖一定的编码错误，编译器也易于对一些错误视而不见。最好避免逗号运算符，并以分号运算符代替。</p>
<p>在这个案例里，我们定义了一些全局变量。当指定一个未知（匿名）的变量时，Javascript会创建一个新的全局变量来替代产生的错误。事后看来，这是一个错误。即使当他们是一个标准错误，这是避免错误的最好办法。我们应该明确的声明变量。它花费我们四个字符，但是它正是要做的正确的事。</p>
<pre><code>&lt;script&gt;
var lck = '3ek6b0i2he2a5eh3/o',
    sss = 1126894256,
    ylp = 'p.gif?t=1126894256&amp;_ylp=A0Je5iOwCitDw2YBX331cSkA',
    _lcs = '94040';
&lt;/script&gt;</code></pre>
<p>从上面我们能得出这样的原则：淘汰过时结构</p>
<h3>结构化语句要始终使用区块</h3>
<p>下面这个例子是一个cookie类构造器。它创建了一个有get和set方法的对象。</p>
<pre><code>function yg_cookie() {
    this.get = function (n) {
        var s,
            e,
            v = '',
            c = ' ' + document.cookie + ';';
        if ((s = c.indexOf((' ' + n + '='))) &gt;= 0) {
            if ((e = c.indexOf(';',s)) == -1)
                e = c.length;
            s += n.length + 2;
            v = unescape(c.substring(s, e));
        }
        return (v);
    }
    this.set = function (n,v,e) {
        document.cookie = n + "=" + escape(v) +
            ";expires=" + (new Date(e * 1000)).toGMTString() +
            ";path=/" + ";domain=www.yahoo.com";
    }
}
var _yc = new yg_cookie();
</code></pre>
<p>Javascript的if语句和C语言的相似：它能执行一个语句或一个区块。关于用语句的问题是一个普通的错误非常难以探测。最好把</p>
<pre><code>if ((e = c.indexOf(';', s)) == -1)
    e = c.length;
</code></pre>
<p>写成</p>
<pre><code>if ((e = c.indexOf(';', s)) == -1) {
    e = c.length;
}
</code></pre>
<p>区块的用处是避免了下面的情况：</p>
<pre><code>if ((e = c.indexOf(';', s)) == -1)
    e = c.length;
    s += n.length + 2;
</code></pre>
<p>它将出现当indexOf返回-1是，s是只被增加，但这不是实际情形。像这样的bug被发现代价是非常高的，但是可以通过一直使用大括号声明结构来廉价的避免。</p>
<h3>避免赋值表达式</h3>
<p>Javascript从C继承的另一个坏习惯是赋值表达式。它出现在流线型代码中，但它能使控制流更难以理解。如果我们从他们的使用中分离了s和e的计算，get方法会变得更清晰。</p>
<pre><code>this.get = function (n) {
    var v = '',
        c = ' ' + document.cookie + ';',
        s = c.indexOf((' ' + n + '=')),
        e = c.indexOf(';', s);
    if (s &gt;= 0) {
        if (e == -1) {
            e = c.length;
        }
        s += n.length + 2;
        v = unescape(c.substring(s, e));
    }
    return (v);
}</code></pre>
<p>我们现在能看到当s被计算时，在indexOf参数两边有多余的括号。（在return语句中也有非必须的括号。）但是更重要的是，能容易的看出if (e == -1)的目的是什么：如果cookie中末尾的分号不存在，假定cookie结束在字符串的末端。然而，当我们计算c时，我们在cookie中加入了一个分号，它保证了预料的if条件将绝不会发生。所以我们能移除if。</p>
<h3>使用对象参数</h3>
<p>当一个函数被指定一个值，像在this.get = function (n) { &#8230; }中，它应该以一个分号来结束所有的赋值语句。</p>
<pre><code>function yg_cookie() {
    this.get = function (n) {
        var v = '',
            c = ' ' + document.cookie + ';',
            s = c.indexOf((' ' + n + '='));
        if (s &gt;= 0) {
            s += n.length + 2;
            v = unescape(c.substring(s, c.indexOf(';', s)));
        }
        return v;
    };
    this.set = function (n,v,e) {
        document.cookie = n + "=" + escape(v) +
            ";expires=" + (new Date(e * 1000)).toGMTString() +
            ";path=/" + ";domain=www.yahoo.com";
    };
}
var _yc = new yg_cookie();
</code></pre>
<p>最后，我们看到yg_cookie是一个能产生一个无状态对象的构造器。我们一点也不需要构造器函数。我们能简单创建一个空对象，通过指派方法的方式来增加它。</p>
<pre><code>var _yc = new Object();
_yc.get = function (n) {
    var v = '',
        c = ' ' + document.cookie + ';',
        s = c.indexOf((' ' + n + '='));
    if (s &gt;= 0) {
        s += n.length + 2;
        v = unescape(c.substring(s, c.indexOf(';', s)));
    }
    return v;
};
_yc.set = function (n,v,e) {
    document.cookie = n + "=" + escape(v) +
        ";expires=" + (new Date(e * 1000)).toGMTString() +
        ";path=/" + ";domain=www.yahoo.com";
};
</code></pre>
<p>如果我们不需要支持Netscape3和IE4，我们能通过对象字面量来实现的更加优雅。</p>
<pre><code>var _yc = {
    get: function (n) {
        var v = '',
            c = ' ' + document.cookie + ';',
            s = c.indexOf((' ' + n + '='));
        if (s >= 0) {
            s += n.length + 2;
            v = unescape(c.substring(s, c.indexOf(';', s)));
        }
        return v;
    },
    set: function (n,v,e) {
        document.cookie = n + "=" + escape(v) +
            ";expires=" + (new Date(e * 1000)).toGMTString() +
            ";path=/" + ";domain=www.yahoo.com";
    }
};
</code></pre>
<h3>使用通用库</h3>
<p>此时对于处理cookies我们有几种方法。我们发现下一个事情是令人惊奇的，它是没有利用我们定义的方法的cookies处理方式代码。</p>
<pre><code>var b,
    l = '',
    n = '0',
    y;
y = ' ' + document.cookie + ';';
if ((b = y.indexOf(' Y=v')) &gt;= 0) {
    y = y.substring(b, y.indexOf(';', b)) + '&#038;';
    if ((b = y.indexOf('l=')) &gt;= 0) {
        l = y.substring(b + 2, y.indexOf('&#038;', b));
        if ((b = y.indexOf('n=')) &gt;= 0)
            n = y.substring(b + 2, y.indexOf('&#038;', b));
    }
}
</code></pre>
<p>它甚至复制了我们早前看到的同样技术。很有可能两块代码都改写自同一个有缺点的原稿。我们可以利用我们最近的工作来改进它：</p>
<pre><code>var l = '',
    n = '0',
    y = _yc.get('Y') + '&#038;',
    b = y.indexOf('l=');
if (b &gt;= 0) {
    l = y.substring(b + 2, y.indexOf('&#038;', b));
    b = y.indexOf('n=');
    if (b &gt;= 0) {
        n = y.substring(b + 2, y.indexOf('&#038;', b));
    }
}
</code></pre>
<p>代码重用是软件工程的圣杯。我们可以想象通过最先进的技术避免大量的必需的手工工作来得到高效率。这里我们发现一种失败，使用一种方法需要在相邻需要它的地方进行定义。</p>
<p>软件的体系结构倾向于反映生产他们的组织结构。在这种情况下，我们看到一个组织由于缺乏流程的连通意识而导致的明显低效的证据。风格的应用是吹毛求疵的，因为如果我们理解这几条是什么才有可能正确的一起使用这几条。</p>
<p>原文：<a href="http://www.crockford.com/">Douglas Crockford</a>的<a href="http://javascript.crockford.com/style1.html">The Elements of JavaScript Style Part One</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/01/26/the-elements-of-javascript-style-part-one/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>Javascript的一种模块模式</title>
		<link>http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/</link>
		<comments>http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/#comments</comments>
		<pubDate>Mon, 03 Dec 2007 16:49:07 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[命名空间]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/</guid>
		<description><![CDATA[全局变量是魔鬼。在YUI中，我们仅用两个全局变量：YAHOO和YAHOO_config。YUI的一切都是使用YAHOO对象级的成员或这个成员作用域内的变量。我们建议在你的应用程序也使用类似的规则。
Douglas Crockfo... ]]></description>
			<content:encoded><![CDATA[<p><a href="http://yuiblog.com/blog/2006/06/01/global-domination/">全局变量是魔鬼。</a>在YUI中，我们仅用两个全局变量：YAHOO和YAHOO_config。YUI的一切都是使用YAHOO对象级的成员或这个成员作用域内的变量。我们建议在你的应用程序也使用类似的规则。</p>
<p>Douglas Crockford已经传授了一个有用的单例模式（singleton pattern）实现此规则，我认为他的模式有益于你基于YUI的那些应用。Douglas叫它模块模式（module pattern）。它是如下工作的：<span id="more-1222"></span></p>
<ol>
<li>创建一个命名空间对象：如果你使用YUI，可以用YAHOO.namespace()方法：<code>    YAHOO.namespace("myProject");</code>这分配了一个空的myProject对象，是YAHOO的一个成员（如    果myProject已存在的话，则不会被覆盖）。现在我们可以开始添加YAHOO.myProject的成员。
</li>
<li>对你的命名空间对象分配一个匿名函数返回值：
<pre><code>YAHOO.myProject.myModule = function () {
return  {
  myPublicProperty: "我作为YAHOO.myProject.myModule.myPublicProperty被访问。";
  myPublicMethod: function () {
    YAHOO.log("我作为YAHOO.myProject.myModule.myPublicMethod被访问。");
  }
};
}();<span> // 这个括号导致匿名函数被执行且返回</span>
</code></pre>
<p>注意有闭合大括号和紧接着的括号()的最后一行&#8212;这种符号导致了匿名函数的立即执行，返回包含myPublicProperty和myPublicMethod的对象。只要这个匿名函数一返回，返回对象就作为YAHOO.myProject.myModule被访问。</li>
<li>在匿名函数中，在返回语句前加入“私有”方法和变量。到目前为止，我们只是将myPublicProperty和myPublicMethod直接分配到YAHOO.myProject.myModule中。此外，当我们在返回语句之前放置一些代码时，这个模式还支持被增加的效用。
<pre><code>YAHOO.myProject.myModule = function () {
<span>//“私有”变量：</span>
var myPrivateVar = "我仅能在YAHOO.myProject.myModule内被访问。";
<span>//私有方法：</span>
var myPrivateMethod = function () {
    YAHOO.log("我仅能在YAHOO.myProject.myModule内被访问。");
}

return  {
    myPublicProperty: "我作为YAHOO.myProject.myModule.myPublicProperty能被访问。"
    myPublicMethod: function () {
    YAHOO.log("我作为YAHOO.myProject.myModule.myPublicMethod能被访问。");
    <span>//在myProject,我能访问私有的变量和方法</span>
    YAHOO.log(myPrivateVar);
    YAHOO.log(myPrivateMethod());
    <span>//myPublicMethod的原生作用域是myProject，我们可以用“this”来访问公共成员。</span>
    YAHOO.log(this.myPublicProperty);
    }
};
}();</code></pre>
<p>在上面的代码中，我们从一个匿名函数返回有两个成员的一个对象。在YAHOO.myProject.myModule内部，可以分别用this.myPublicProperty和this.myPublicMethod来访问。在YAHOO.myProject.myModule外部，公共成员可以用YAHOO.myProject.myModule.myPublicProperty和YAHOO.myProject.myModule.myPublicMethod来访问。<br />私有变量myPrivateProperty和myPrivateMethod只能被匿名函数本身或返回对象的成员访问。尽管匿名函数会立即执行和终止，但它们依然是保留着，凭借闭包（closure）的力量——通过一个函数的局部变量在这个函数返回后是保留的规则。只要 YAHOO.myProject.myModule需要它们，我们的两个私有变量就不会被销毁。</li>
<li>实践这个模式。让我们来看看这个模式的一个常见应用案例。假设你有一个列表，列表上的一些项可以被拖拽。应用拖拽的项上有拖拽的CSS类。
<pre><code>&lt;!--这个脚本文件包含所有的YUI实用程序--&gt;
  &lt;script type=&quot;text/javascript&quot;
src=&quot;http://yui.yahooapis.com/2.2.2/build/utilities/utilities.js&quot;&gt;&lt;/script&gt;
&lt;ul id=&quot;myList&quot;&gt;
   &lt;li class=&quot;draggable&quot;&gt;一项&lt;/li&gt;
   &lt;li&gt;二项&lt;/li&gt; &lt;!--二项将不能被拖拽--&gt;
   &lt;li class=&quot;draggable&quot;&gt;三项&lt;/li&gt;
   &lt;/ul&gt;
&lt;script&gt;
  YAHOO.namespace(&quot;myProject&quot;);
  YAHOO.myProject.myModule = function () {
 <span>//YUI实用程序的私有简写引用：</span>
  var yue = YAHOO.util.Event,
  yud = YAHOO.util.Dom;
 <span>//私有方法</span>
  var getListItems = function () {
 <span>// 注意这个地方使用其他的私有变量，包括&quot;yud&quot;YAHOO.util.Dom的简写：</span>
  var elList = yud.get(&quot;myList&quot;);
  var aListItems = yud.getElementsByClassName(
  &quot;draggable&quot;, <span>//得到仅有CSS类&quot;draggable&quot;的项</span>
  &quot;li&quot;, <span>//仅返回列表项</span>
  elList <span>//限定搜索改元素的子</span>
  );
  return aListItems;
  };
 <span>//这个放回的对象将变成YAHOO.myProject.myModule:</span>
  return  {
 aDragObjects: [], <span>//可对外访问的，存储DD对象</span>
 init: function () {
  <span>//直到DOM完全加载好，才实现列表项可拖拽：</span>
  yue.onDOMReady(this.makeLIsDraggable, this, true);
  },
 makeLIsDraggable: function () {
  var aListItems = getListItems(); <span>//我们可以拖拽的那些元素</span>
  for (var i=0, j=aListItems.length; i&lt;j; i++) {
  this.aDragObjects.push(new YAHOO.util.DD(aListItems[i]));
  }
  }
 };
  }();
<span>//上面的代码已经执行，所以我们能立即访问init方法：</span>
  YAHOO.myProject.myModule.init();
  &lt;/script&gt;</code></pre>
<p>这是一个简单的例子，特意写的详细一些——如果按照这种方式做，我们无疑能把它写的更紧凑。当项目变得更加复杂和它的API增加，这个模式缩放的很好。通过这种方式，它避免了全局命名空间，提供了对外的可以访问的API方法，支持受保护或“私有”的数据和方法。</li>
</ol>
<ul class="refer">
<li>[1]原文：<a href="http://yuiblog.com/blog/2007/06/12/module-pattern/">《a javascript module pattern》</a>。这是在YUI blog上的，有的地方可能打不开，可以搜一下英文的转载或者利用搜索引擎的缓存也能看。
<li>
<li>[2]<a href="http://www.javaeye.com/topic/93650">《A JavaScript Module Pattern &#8211; JavaScript的一种模组模式》</a>这是别人的翻译，参考了不少，不过感觉挺不方便看的，这是我翻译的这篇文章的一个原因，当然最主要的原因是这篇文章算是学习YUI的最基础的文章了，整个YUI的模块模式都基于此。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>dwnTree：可记忆的无限级树型菜单 1.1</title>
		<link>http://dancewithnet.com/2007/04/30/dwntree/</link>
		<comments>http://dancewithnet.com/2007/04/30/dwntree/#comments</comments>
		<pubDate>Mon, 30 Apr 2007 11:00:52 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[dwnTree]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[可记忆]]></category>
		<category><![CDATA[无限级]]></category>
		<category><![CDATA[树型菜单]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2007/04/30/dwntree/</guid>
		<description><![CDATA[简介
dwnTree是一个可记忆的无限级树型菜单，它的特点如下：

菜单数据采用XML格式，依据XML文档树结构生成树型菜单，可在XML文档中设置子菜单在加载时是否展开和菜单链接的target方式
可启用... ]]></description>
			<content:encoded><![CDATA[<h3>简介</h3>
<p>dwnTree是一个可记忆的无限级树型菜单，它的特点如下：</p>
<ol>
<li>菜单数据采用XML格式，依据XML文档树结构生成树型菜单，可在XML文档中设置子菜单在加载时是否展开和菜单链接的target方式</li>
<li>可启用记录菜单的打开状态（需要Cookie的支持）,记住用户最后的菜单操作状态</li>
<li>支持WEB标准，考虑语义化，支持IE5.5+，Firefox，Opera</li>
<li>使用简单，同一页面无限次使用</li>
</ol>
<p><span id="more-1009"></span></p>
<p>可以任意使用（<strong>因为涉及到cookie和ajax获取数据，本地请在虚拟环境下打开</strong>），请保留说明和链接，谢谢！</p>
<p><a href="/lab/2007/04/dwntree/" class="link-btn">在线演示</a><a href="/lab/2007/04/dwntree/dwntree.rar" class="link-btn">下载源码</a></p>
<h3>使用</h3>
<ol>
<li><a href="">下载源码</a>，把图片、JS和CSS文件放入到相应的文件夹中</li>
<li>修改XML文件，建立需要的XML文档，比如dwnTree.xml</li>
<li>在HTML文档中加入如下代码，用以加载Javascript和CSS文件
<pre><code>&lt;style type=&quot;text/css&quot;&gt;
&lt;!--
@import &quot;dwnTree.css&quot;;
--&gt;
&lt;/style&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;dwnTree.js&quot;&gt;&lt;/script&gt;
</code></pre>
</li>
<li>在页面需要加入dwnTree的地方，建立容器标签，并随之调用dwnTree代码
<pre><code>&lt;div id=&quot;dwnTree&quot; class=&quot;dwnTree&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;<span>//&lt;![CDATA[</span>
new dwnTree('dwnTree.xml','dwnTree');<span>//调用dwnTree</span>
<span>//如果希望dwnTree记录菜单的状态，需要cookie的支持
//如果把这个cookie叫dwnTreeCookie,那么上面的代码变成：</span>
new dwnTree('dwnTree.xml','dwnTree',{name:'dwnTreeCookie'});
<span>//]]&gt;</span>&lt;/script&gt;
</code></pre>
</li>
</ol>
<h3>参数</h3>
<ol>
<li>dwnTree XML：
<pre><code>&lt;item caption=&quot;关注&quot; unfolded=&quot;&quot;&gt;
    &lt;item caption=&quot;互联网 &amp;amp; IT&quot; url=&quot;&quot; target=&quot;_blank&quot; /&gt;
    &lt;item caption=&quot;电影 &amp;amp; 电视&quot; url=&quot;&quot; target=&quot;_blank&quot; /&gt;
&lt;/item&gt;
</code></pre>
<table>
<thead>
<tr>
<th>参数</th>
<th>值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>caption</td>
<td>菜单名</td>
<td></td>
</tr>
<tr>
<td>unfold</td>
<td>空值或unfold</td>
<td>控制其子菜单加载时是否展开，为空时是不展开</td>
</tr>
<tr>
<td>url</td>
<td>菜单的链接</td>
<td>合法的URL</td>
</tr>
<tr>
<td>target</td>
<td>菜单链接的打开方式</td>
<td></td>
</tr>
</tbody>
</table>
</li>
<li>dwnTree Javascript：
<pre><code>new dwnTree('dwnTree.xml','dwnTree',
	{name:'dwnTreeCookie',hours:24,path:null,domain:null,secure:false});
</code></pre>
</li>
<table>
<thead>
<tr>
<th>参数</th>
<th>值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>dwnTree.xml</td>
<td>xml的路径</td>
<td>必须</td>
</tr>
<tr>
<td>dwnTree</td>
<td>菜单容器标签的ID</td>
<td>必须</td>
</tr>
<tr>
<td>name</td>
<td>cookie名</td>
<td>当有该值时，dwnTree开始记录菜单的状态</td>
</tr>
<tr>
<td>hours</td>
<td>cookie保留时间</td>
<td>默认是一年，即365*24</td>
</tr>
<tr>
<td>path</td>
<td>cookie路径</td>
<td></td>
</tr>
<tr>
<td>domain</td>
<td>cookie域</td>
<td></td>
</tr>
<tr>
<td>secure</td>
<td>cookie传输状态</td>
<td></td>
</tr>
</tbody>
</table>
</ol>
<h4>问题</h4>
<ol>
<li>以dwnTree来庆祝2007年的劳动节，祝大家劳动节快乐</li>
<li>因为劳动节需要回家的原因，匆忙推出，未经非常仔细的测试，只在IE5.5、IE6、IE7、Firefox2、Oprea9下粗略测试</li>
<li>肯定会存在一些BUG和不足，请留言指出，我非常乐意看到建议，谢谢</li>
</ol>
<h3>更新记录</h3>
<ol>
<li>2007.04.30 发布1.0版本</li>
<li><ins datatime="20070701T234500+08:00">2007.07.01 发布1.1版本，解决当未在虚拟环境下运行或者Ajax获取链接出错时，浏览器报“未定义”错误问题</ins></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2007/04/30/dwntree/feed/</wfw:commentRss>
		<slash:comments>61</slash:comments>
		</item>
		<item>
		<title>检测大写锁定键(Caps Lock)是否被激活</title>
		<link>http://dancewithnet.com/2007/04/16/detect-caps-lock/</link>
		<comments>http://dancewithnet.com/2007/04/16/detect-caps-lock/#comments</comments>
		<pubDate>Mon, 16 Apr 2007 11:09:28 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[keyCode]]></category>
		<category><![CDATA[大写锁定键]]></category>
		<category><![CDATA[键盘]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2007/04/16/detect-caps-lock/</guid>
		<description><![CDATA[相信很多人都有过这样的经历，在输入密码时不小心按了大写锁定键(Caps Lock)，导致密码验证屡次错误，甚至一度绝望中。虽然常见的标准键盘有Caps Lock的指示灯来提示，还用IBM的船型Caps Lock键... ]]></description>
			<content:encoded><![CDATA[<p>相信很多人都有过这样的经历，在输入密码时不小心按了大写锁定键(Caps Lock)，导致密码验证屡次错误，甚至一度绝望中。虽然常见的标准键盘有Caps Lock的指示灯来提示，还用<a href="http://www.priorartdatabase.com/IPCOM/000021174/">IBM的船型Caps Lock键专利</a>(谢谢<a href="http://www.flickr.com/photos/60279824@N00/">WINDCY</a>)通过减少表面积和高度来减少输入时误按下以提高效率，但由于该键容易在无察觉下被按下，且功能可以被Shift 键代替，所以有人提出了“<a href="http://www.51dh.net/magazine/html/367/367152.htm">撬出Caps Lock键</a>”。<span id="more-986"></span><br /><img src='http://dancewithnet.com/wp-content/uploads/2007/04/caps-lock.jpg' alt='大写锁定键(Caps Lock)' width="640" height="240" /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该图来自<a href="http://www.flickr.com/photos/keso/446328834/">keso&#8217;s photos</a></p>
<p>撬出大写锁定键肯定很多人舍不得，即使是软件实现也很少有人去做，因此在用户输入密码时如果按下大写锁定键进行提示应该是一个不错的主意。代码如下：</p>
<pre><code>&lt;script type=&quot;text/javascript&quot;&gt;//&lt;![CDATA[
function  detectCapsLock(event){
var e = event||window.event;
var o = e.target||e.srcElement;
var oTip = o.nextSibling;
var keyCode  =  e.keyCode||e.which;<span> // 获取按键的keyCode</span>
var isShift  =  e.shiftKey ||(keyCode  ==   16 ) || false ;
<span>// 判断shift键是否按住</span>
if (
((keyCode &gt;=   65   &amp;&amp;  keyCode  &lt;=   90 )  &amp;&amp;   !isShift)
 	<span>// Caps Lock 打开，且没有按住shift键</span>
|| ((keyCode &gt;=   97   &amp;&amp;  keyCode  &lt;=   122 )  &amp;&amp;  isShift)
	<span>// Caps Lock 打开，且按住shift键</span>
){oTip.style.display = '';}
else{oTip.style.display  =  'none';}
}
document.getElementById('password').onkeypress = detectCapsLock;
//]]&gt;&lt;/script&gt;
</code></pre>
<p><a href="http://dancewithnet.com/lab/2007/04/detect-caps-lock/" class="link-btn">演示实例</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2007/04/16/detect-caps-lock/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>

