<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://prowyh.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fprowyh.spaces.live.com%2fcategory%2fJavaScript%2bNote%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>prowyh's space: JavaScript Note</title><description /><link>http://prowyh.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=catJavaScript%2bNote</link><language>en-US</language><pubDate>Wed, 03 Sep 2008 02:57:19 GMT</pubDate><lastBuildDate>Wed, 03 Sep 2008 02:57:19 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://prowyh.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>-1537263819930693984</live:id><live:alias>prowyh</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>再谈StringBuilder对象</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!432.entry</link><description>&lt;div&gt;在《&lt;a href="http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!425.entry" target="_blank"&gt;JavaScript代码优化一例（文）&lt;/a&gt;》中，曾经引入了高效构造字符串的StringBuilder对象。不过，那里的StringBuilder比较简单，只有append()一个方法，下面给出经过修改的版本，新版本除增强了append()方法之外，还给出了类似C#中StringBuilder对象的appendFormat方法。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;//////////////////////////////////////////////////////////////&lt;br&gt;// StringBuilder&lt;br&gt;function StringBuilder()&lt;br&gt;{&lt;br&gt; this._strings = new Array();&lt;br&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// enhanced append method&lt;/div&gt;
&lt;div&gt;// append(arg1, arg2, ..., argN)&lt;br&gt;StringBuilder.prototype.append = function (str)&lt;br&gt;{&lt;br&gt; var aLen = arguments.length;&lt;br&gt; for (var i = 0; i &amp;lt; aLen; i++)&lt;br&gt; {&lt;br&gt;  this._strings.push(arguments[i]);&lt;br&gt; }&lt;br&gt;};&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// like AppendFormat() method of C# StringBuilder object&lt;/div&gt;
&lt;div&gt;// appendFormat(fmt, arg1, arg2, ..., argN)&lt;br&gt;StringBuilder.prototype.appendFormat = function (fmt)&lt;br&gt;{&lt;br&gt; var re = /{[0-9]+}/g;&lt;br&gt; var aryMatch = fmt.match(re);&lt;br&gt; var aLen = aryMatch.length;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; for (var i = 0; i &amp;lt; aLen; i++)&lt;br&gt; {&lt;br&gt;  fmt = fmt.replace(aryMatch[i], arguments[parseInt(aryMatch[i].replace(/[{}]/g, &amp;quot;&amp;quot;)) + 1]);&lt;br&gt; }&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; this._strings.push(fmt);&lt;br&gt;};&lt;/div&gt;
&lt;div&gt;&lt;br&gt;StringBuilder.prototype.toString = function ()&lt;br&gt;{&lt;br&gt; return this._strings.join(&amp;quot;&amp;quot;);&lt;br&gt;};&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;示例1：&lt;/div&gt;
&lt;div&gt;var sXML = new StringBuilder();&lt;/div&gt;
&lt;div&gt;sXML.append(&amp;quot;&amp;lt;myData&amp;gt;\r\n&amp;quot;);&lt;/div&gt;
&lt;div&gt;sXML.append(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;, name, &amp;quot;&amp;lt;/name&amp;gt;\r\n&amp;quot;);&lt;/div&gt;
&lt;div&gt;sXML.append(&amp;quot;&amp;lt;color&amp;gt;&amp;quot;, color, &amp;quot;&amp;lt;/color&amp;gt;\r\n&amp;quot;);&lt;/div&gt;
&lt;div&gt;sXML.append(&amp;quot;&amp;lt;/myData&amp;gt;\r\n&amp;quot;);&lt;/div&gt;
&lt;div&gt;alert(sXML.toString());&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;示例2：&lt;/div&gt;
&lt;div&gt;var sHTML = new StringBuilder();&lt;/div&gt;
&lt;div&gt;sHTML.appendFormat(&amp;quot;&amp;lt;div style='width:{0}px;height:{1}px;background-color:{2};'&amp;gt;&amp;quot;, width, height, bkcolor);&lt;/div&gt;
&lt;div&gt;sHTML.appendFormat(&amp;quot;&amp;lt;a class='{0}' href='{1}' target='_blank'&amp;gt;{2}&amp;lt;/a&amp;gt;&amp;quot;, className, url, name);&lt;/div&gt;
&lt;div&gt;sHTML.append(&amp;quot;&amp;lt;/div&amp;gt;&amp;quot;);&lt;/div&gt;
&lt;div&gt;divObj.innerHTML = sHTML.toString();&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;由例子可以看出，append()适合于构造简单字符串，appendFormat()适合于构造复杂字符串。&lt;/div&gt;
&lt;div&gt;测试结果显示，append()比appendFormat()快40% ~ 60%。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+%e5%86%8d%e8%b0%88StringBuilder%e5%af%b9%e8%b1%a1&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!432.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!432.entry</guid><pubDate>Mon, 03 Sep 2007 18:15:49 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!432/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!432.entry#comment</wfw:comment><dcterms:modified>2007-09-03T18:15:49Z</dcterms:modified></item><item><title>JavaScript Compiler</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!426.entry</link><description>&lt;div&gt;上文《&lt;a href="http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!425.entry"&gt;JavaScript代码优化一例（文）&lt;/a&gt;》曾引述过一个关于JavaScript性能的比较结果：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; JavaScript与其它语言相比较：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;比编译型的C程序慢5000倍； 
&lt;li&gt;比解释型的Java程序慢100倍； 
&lt;li&gt;比解释型的Perl慢10倍。&lt;/ul&gt;
&lt;p&gt;而且还言及： 
&lt;p&gt;随着Web 2.0以及Ajax概念的提出及相关技术的流行，Web页面应用程序化的趋势越来越明显，人们要求Web页面能够更多地体现传统桌面应用程序的风格与使用体验，而不再是传统Web页面的导航与刷新。在这种应用需求的推动下，原本只是在客户端起到补充与点缀作用的JavaScript代码，越来越成为Web程序设计的主角。而这就使得JavaScript的代码越来越庞大与复杂。 
&lt;p&gt;既然如此，一个合理的推测就是：JavaScript Compiler将会成为未来编译器之战中的主角，或者说，JavaScript代码的编译会成为未来的技术趋势。 
&lt;p&gt;为何JavaScript一直没有以compiled code形式出现，估计可能有如下几个原因： 
&lt;ul&gt;
&lt;li&gt;角色：早期的Web Page以展示型为主，JavaScript代码非常简单，性能并不是突出问题。 
&lt;li&gt;安全：文本形式的JavaScript Code能够有效避免病毒和恶意攻击代码（虽然目前的带毒JavaScript代码并不少见）。 
&lt;li&gt;形式：大部分的JavaScript代码都是嵌入在页面里的，没有做到代码与页面的分离。&lt;/ul&gt;
&lt;p&gt;当然，可能还有其它原因。 
&lt;p&gt;归结起来，角色可能是最主要的原因，因为安全可以通过Sandbox式的运行环境与系统隔离，即使是compiled code，也仍然只能访问DOM和BOM。形式是最不重要的，这只是一个编程习惯问题。 
&lt;p&gt;角色正在起变化！随着Web 2.0以及Ajax的大量应用，Web Page正在演变为Web Application，JavaScript已经从原来不起眼的小角色，逐步成为编程的主导力量。这个时候，期待JavaScript Compiler就具有了合理性。 
&lt;p&gt;非常巧合，刚好读到Richard MacManus的blog《&lt;a title="Permanent Link to Why Google and Microsoft need Javascript compilers" href="http://blogs.zdnet.com/web2explorer/?p=197" rel=bookmark&gt;&lt;font color="#666666"&gt;Why Google and Microsoft need Javascript compilers&lt;/font&gt;&lt;/a&gt;》，文中称Google和Microsoft正在开发JavaScript Compilers，不过，作者所言并非我这里的意思，而是将其它高级语言（如Java、C#等）代码编译为JavaScript代码（所以，合适的名称应该是JavaScript Translator），以充分利用熟悉其它语言的开发者开发Ajax Application。 
&lt;p&gt;Richard MacManus在文中提到Microsoft正在进行的一个项目Script#，是将C#语言代码编译为JavaScript代码。 
&lt;p&gt;Nikhil Kothari（an architect on the Web Platform and Tools team at Microsoft）在其blog中介绍了&lt;a href="http://www.nikhilk.net/ScriptSharpIntro.aspx" target="_blank"&gt;Script#项目&lt;/a&gt;的情况。 
&lt;p&gt;不管是Google的Java -&amp;gt; JavaScript编译器，还是Microsoft的C# -&amp;gt; JavaScript编译器（Script#），最终只能导致Client端的代码越来越重，Microsoft的spaces.live.com已经让我们体会到过重的Scripting的结果了。 
&lt;p&gt;so, doing JavaScript code optimization, expecting JavaScript compiler! 
&lt;p&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+JavaScript+Compiler&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!426.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!426.entry</guid><pubDate>Wed, 29 Aug 2007 18:02:18 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!426/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!426.entry#comment</wfw:comment><dcterms:modified>2007-08-29T18:45:01Z</dcterms:modified></item><item><title>JavaScript代码优化一例（文）</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!425.entry</link><description>&lt;div&gt;JavaScript（JScript，ECMAScript）主要作为Web的客户端编程语言，以浏览器为宿主运行环境，通过DOM（Document Object Model，文档对象模型）和BOM（Browser Object Model，浏览器对象模型）接口所呈现（expose）的对象和方法，来操纵页面的HTML元素。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;早期的JavaScript代码主要完成两方面的工作，一是在客户端进行输入验证（以避免由服务器进行验证而产生的网络传输）；二是使页面产生一定的动态效果（如下拉菜单的动态显示，颜色与字体的变化等）。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;随着Web 2.0以及Ajax概念的提出及相关技术的流行，Web页面应用程序化的趋势越来越明显，人们要求Web页面能够更多地体现传统桌面应用程序的风格与使用体验，而不再是传统Web页面的导航与刷新。在这种应用需求的推动下，原本只是在客户端起到补充与点缀作用的JavaScript代码，越来越成为Web程序设计的主角。而这就使得JavaScript的代码越来越庞大与复杂。此时，JavaScript代码的优化就越发显得重要。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;所谓代码优化，主要是指代码所占空间（代码运行时所占的内存空间）和运行时间两个方面，早期由于机器内存资源的限制，算法研究者对空间和时间的优化给予同样的重视，空间上节省一个字节和时间上减少一次循环同样重要。现在，由于机器内存资源相对充裕（当然，只是相对而言），算法（代码）的优化，更多地集中于运行时间上，特别对JavaScript代码而言，更是如此。关于JavaScript的运行效率，Syracuse大学的Geoffrery Fox给出了一个比较结果&lt;sup&gt;[1]&lt;/sup&gt;：&lt;/div&gt;
&lt;div&gt;&lt;br&gt; JavaScript与其它语言相比较：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;比编译型的C程序慢5000倍； 
&lt;li&gt;比解释型的Java程序慢100倍； 
&lt;li&gt;比解释型的Perl慢10倍。&lt;/ul&gt;
&lt;p&gt;所以，要提高JavaScript的运行性能，除了寄希望于将来能有更高性能的JavaScript解释器之外，提高我们代码的效率也非常重要。关于JavaScript代码的优化，文献&lt;sup&gt;[1]&lt;/sup&gt;给出了一些很好的建议，有兴趣者可以参考，此处不赘。 
&lt;p&gt;&lt;br&gt;优化实例 
&lt;p&gt;下面通过一个工作实例，来具体看看JavaScript代码的优化。 
&lt;p&gt;这是一个内部信息系统中的权限分配模块，界面如图1（见&lt;a href="http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!403.entry" target="_blank"&gt;此文的代码部分&lt;/a&gt;，如果看不到，则有可能ask.com上的图片资源也被封掉了，唉.......）所示。&lt;br&gt; &lt;br&gt;其中，功能权限是指对系统功能模块（体现为菜单项）的使用权限，对象权限是指用户对信息对象的访问（读、写、改、删）权限。管理员通过此界面对项目组成员及其权限进行配置。代码的功能是找出选中的功能权限项目以及对象权限项目。最简单的办法是通过遍历HTML的&amp;lt;INPUT&amp;gt;元素。 
&lt;p&gt;功能权限部分的遍历是相对简单的，通过INPUT元素的id的模式匹配，即可一次遍历所有元素，难点是对象权限部分。 
&lt;p&gt;未优化的JavaScript代码是通过三重循环完成所有元素的遍历的，整个代码耗时1281毫秒，这显然是不能接受的，所以需要优化。 
&lt;p&gt;下面是优化后的版本： 
&lt;div&gt;&lt;br&gt;// 功能权限及对象列表&lt;br&gt;var functorListEx = new StringBuilder();&lt;br&gt;var objectListEx = new StringBuilder();&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// 所有INPUT元素的集合&lt;br&gt;var coll = document.getElementsByTagName(&amp;quot;INPUT&amp;quot;);&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// 用于模式匹配的正则表达式&lt;br&gt;var fnRE = /functor_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}/i;&lt;br&gt;var objRE = /object_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}$/i;&lt;br&gt;var objRE_r = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_r/i;&lt;br&gt;var objRE_a = /object_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_a/i;&lt;br&gt;var objRE_m = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_m/i;&lt;br&gt;var objRE_d = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_d/i;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// 中间数据结构&lt;br&gt;var aryObjList = new Array();&lt;br&gt;var aryRList = new Array();&lt;br&gt;var aryAList = new Array();&lt;br&gt;var aryMList = new Array();&lt;br&gt;var aryDList = new Array();&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;for (var i = 0; i &amp;lt; coll.length; i++)&lt;br&gt;{&lt;br&gt; // 通过一次遍历所有元素，填充几个中间数据结构&lt;br&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// 对中间数据结构的后续处理&lt;br&gt;for (var i = 0; i &amp;lt; aryObjList.length; i++)&lt;br&gt;{&lt;br&gt; var _id = aryObjList[i];&lt;br&gt; var _r = aryRList[_id] == null ? &amp;quot;&amp;quot; : aryRList[_id];&lt;br&gt; var _a = aryAList[_id] == null ? &amp;quot;&amp;quot; : aryAList[_id];&lt;br&gt; var _m = aryMList[_id] == null ? &amp;quot;&amp;quot; : aryMList[_id];&lt;br&gt; var _d = aryDList[_id] == null ? &amp;quot;&amp;quot; : aryDList[_id];&lt;br&gt; objectListEx.append(_id + &amp;quot;:&amp;quot; + _r + &amp;quot;:&amp;quot; + _a + &amp;quot;:&amp;quot; + _m + &amp;quot;:&amp;quot; + _d + &amp;quot;;&amp;quot;);&lt;br&gt;}&lt;/div&gt;
&lt;div&gt;&lt;br&gt;从结果显示的运行时间上来看，未优化的代码耗时1281毫秒（例中的coll.length == 318），而优化后的代码耗时47毫秒。可见，优化的效果是明显的。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;本例的优化主要是消除了代码的内循环，通过一次遍历就完成了functorListEx以及objectListEx所需要的几个中间数据结构（数组）的构建，后续的处理是由中间数据结构构建objectListEx，而aryObjList.length远远小于coll.length。所以，优化后的代码效率远远高于原来的代码。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;效率分析&lt;/div&gt;
&lt;div&gt;&lt;br&gt;下面来简单分析一下优化前后的代码效率。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;令代码的数据规模（即coll.length）为n。优化前，构建functorList的运行时间为O(n)，而构建objectList的运行时间为O(n&lt;sup&gt;3&lt;/sup&gt;)，所以，整个代码的运行时间&lt;/div&gt;
&lt;div&gt;&lt;br&gt;T&lt;sub&gt;nopt&lt;/sub&gt; = O(n) + O(n&lt;sup&gt;3&lt;/sup&gt;) = O(n&lt;sup&gt;3&lt;/sup&gt;)&lt;/div&gt;
&lt;div&gt;&lt;br&gt;优化后，构建functorListEx及中间数据结构的运行时间为O(n)，构建objectListEx的运行时间为O(m)，此处m &amp;lt; n。所以，整个代码的运行时间&lt;/div&gt;
&lt;div&gt;&lt;br&gt;T&lt;sub&gt;opt&lt;/sub&gt; = O(n) + O(m) = O(n)&lt;/div&gt;
&lt;div&gt;&lt;br&gt;优化前，代码的运行时间为指数幂时间（这是最糟糕的！），优化后的运行时间为线性时间（这是相当好的结果！），由此可以看出，代码优化与否，差别是相当大的。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;当然，代码优化是以一个能够正确工作的代码基（code base）为前提的。所以，先让程序正确地工作，然后再努力使其快速地正确工作 &lt;sup&gt;[3]&lt;/sup&gt; 。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;注：&lt;br&gt;1、 上述代码中的StringBuilder对象录自文献&lt;sup&gt;[1]&lt;/sup&gt;，就像C#一样，这个StringBuilder对象也是构造字符串的高效对象。&lt;/div&gt;
&lt;div&gt;2、 由于篇幅的限制，文中省略了具体的代码实现，有兴趣者可以在笔者的blog（prowyh.spaces.live.com）中找到完整的代码实现。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;参考文献&lt;br&gt;1. JavaScript高级程序设计，Nicholas C. Zaks著，曹力 张欣等译，人民邮电出版社&lt;br&gt;2. JavaScript: The Definitive Guide, 5th Edition，David Flanagan，O’Reilly&lt;br&gt;3. C++ Coding Standards, Herb Sutter, Andrei Alexandrescu, 人民邮电出版社&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;【补注】 &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;此文发于《程序员》杂志2007年第8期，并改正了杂志上几处小的排印错误。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;今天看到aimingoo的blog &lt;a href="http://blog.csdn.net/aimingoo/archive/2007/08/29/1764224.aspx" target="_blank"&gt;再议《JavaScript代码优化一例》&lt;/a&gt;，对拙文的JavaScript代码优化进行了再探讨，从多个方面进行了更细致的优化，非常感谢！&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;以前曾写过一文《&lt;a href="http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!293.entry"&gt;JavaScript学习笔记（之一）&lt;/a&gt;》，是从阅读spaces.live.com以及gmail.com的JavaScript代码有感而发，谓之：现在的JavaScript代码让人看不懂。JavaScript是一个很小巧的语言，但由于兼有函数式和过程式语言的特点而使得Coding非常灵活，这也就使得代码优化大有可为的空间。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;正好今天读完Scott Meyers的Effective系列的最后一本《Effective STL》，Item 47: Avoid producing write-only code，读来深有感触。代码如何写得既correct，又effective，同时又不失readable，确实not easy，这样的代码才可以称得上beautiful code!&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+JavaScript%e4%bb%a3%e7%a0%81%e4%bc%98%e5%8c%96%e4%b8%80%e4%be%8b%ef%bc%88%e6%96%87%ef%bc%89&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!425.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!425.entry</guid><pubDate>Wed, 29 Aug 2007 16:19:30 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!425/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!425.entry#comment</wfw:comment><dcterms:modified>2007-08-31T01:17:30Z</dcterms:modified></item><item><title>JavaScript代码优化</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!403.entry</link><description>&lt;div&gt; 如图为某信息系统的权限设置模块之用户界面：&lt;/div&gt;
&lt;div&gt;&lt;img src="http://mystuff.ask.com/servlet/snipit_image_proxy?uid=b6c75159f83fb178253c52eafa14db41&amp;amp;img_guid=05b59254b7b142565def4e08c196877b&amp;amp;locale=en_US"&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;如何获取用户的功能权限和对象权限的设置信息，还是大有讲究的。下面的代码列表1为未优化的JavaScript代码：&lt;/div&gt;
&lt;div&gt;JavaScript Code List 1:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// non-optimized version&lt;/div&gt;
&lt;div&gt;var functorList = new StringBuilder();&lt;br&gt;var objectList = new StringBuilder();&lt;br&gt;var coll = document.getElementsByTagName(&amp;quot;INPUT&amp;quot;);&lt;/div&gt;
&lt;div&gt;// one pass scan to traverse the nodes collection coll to build functorList&lt;br&gt;for (var i = 0; i &amp;lt; coll.length; i++)&lt;br&gt;{&lt;br&gt; var _obj = coll[i];&lt;br&gt; if (_obj.type != &amp;quot;checkbox&amp;quot;) continue;&lt;br&gt; &lt;br&gt; if (_obj.id.indexOf(&amp;quot;functor_&amp;quot;) &amp;gt;= 0 &amp;amp;&amp;amp; _obj.checked == true)&lt;br&gt; {&lt;br&gt;  var id = _obj.id;&lt;br&gt;  id = id.substring(&amp;quot;functor_&amp;quot;.length, id.length);&lt;br&gt;  functorList.append(id + &amp;quot;;&amp;quot;);&lt;br&gt; }&lt;br&gt;}&lt;/div&gt;
&lt;div&gt;// multi-pass scan to build objectList&lt;br&gt;for (var i = 0; i &amp;lt; coll.length; i++)&lt;br&gt;{&lt;br&gt; var _obj = coll[i];&lt;br&gt; if (_obj.type == &amp;quot;checkbox&amp;quot; &amp;amp;&amp;amp; _obj.id.indexOf(&amp;quot;object_&amp;quot;) &amp;gt;= 0)&lt;br&gt; {&lt;br&gt;  if (_obj.id.indexOf(&amp;quot;_parent&amp;quot;) &amp;gt; 0 || _obj.id.indexOf(&amp;quot;_child&amp;quot;) &amp;gt; 0) continue;&lt;br&gt;  if (_obj.id.indexOf(&amp;quot;_r&amp;quot;) &amp;gt; 0 || _obj.id.indexOf(&amp;quot;_a&amp;quot;) &amp;gt; 0 || _obj.id.indexOf(&amp;quot;_m&amp;quot;) &amp;gt; 0 || _obj.id.indexOf(&amp;quot;_d&amp;quot;) &amp;gt; 0) continue;&lt;/div&gt;
&lt;div&gt;  var pid = _obj.id;&lt;br&gt;  var gid = pid.replace(/object_/g, &amp;quot;&amp;quot;);&lt;br&gt;  var orList = new StringBuilder();&lt;br&gt;  orList.append(gid + &amp;quot;:&amp;quot;);&lt;br&gt;  &lt;br&gt;  for (var k = 0; k &amp;lt; coll.length; k++)&lt;br&gt;  {&lt;br&gt;   var _objK = coll[k];&lt;br&gt;   if (_objK.type == &amp;quot;checkbox&amp;quot; &amp;amp;&amp;amp; _objK.id == pid + &amp;quot;_r&amp;quot; &amp;amp;&amp;amp; _objK.checked)&lt;br&gt;   {&lt;br&gt;    for (var r = 0; r &amp;lt; coll.length; r++)&lt;br&gt;    {&lt;br&gt;     var _objR = coll[r];&lt;br&gt;     if (_objR.type == &amp;quot;radio&amp;quot; &amp;amp;&amp;amp; _objR.getAttribute(&amp;quot;name&amp;quot;) == &amp;quot;radio_&amp;quot; + gid + &amp;quot;_r&amp;quot; &amp;amp;&amp;amp; _objR.checked)&lt;br&gt;     {&lt;br&gt;      orList.append(&amp;quot;r_&amp;quot; + _objR.value + &amp;quot;:&amp;quot;);&lt;br&gt;      break;&lt;br&gt;     }&lt;br&gt;    }&lt;br&gt;   }&lt;br&gt;   else if (_objK.type == &amp;quot;checkbox&amp;quot; &amp;amp;&amp;amp; _objK.id == pid + &amp;quot;_a&amp;quot; &amp;amp; _objK.checked)&lt;br&gt;   {&lt;br&gt;    orList.append(&amp;quot;a_&amp;quot; + &amp;quot;:&amp;quot;);&lt;br&gt;   }&lt;br&gt;   else if (_objK.type == &amp;quot;checkbox&amp;quot; &amp;amp;&amp;amp; _objK.id == pid + &amp;quot;_m&amp;quot; &amp;amp;&amp;amp; _objK.checked)&lt;br&gt;   {&lt;br&gt;    for (var m = 0; m &amp;lt; coll.length; m++)&lt;br&gt;    {&lt;br&gt;     var _objM = coll[m];&lt;br&gt;     if (_objM.type == &amp;quot;radio&amp;quot; &amp;amp;&amp;amp; _objM.getAttribute(&amp;quot;name&amp;quot;) == &amp;quot;radio_&amp;quot; + gid + &amp;quot;_m&amp;quot; &amp;amp;&amp;amp; _objM.checked)&lt;br&gt;     {&lt;br&gt;      orList.append(&amp;quot;m_&amp;quot; + _objM.value + &amp;quot;:&amp;quot;);&lt;br&gt;      break;&lt;br&gt;     }&lt;br&gt;    }&lt;br&gt;   }&lt;br&gt;   else if (_objK.type == &amp;quot;checkbox&amp;quot; &amp;amp;&amp;amp; _objK.id == pid + &amp;quot;_d&amp;quot; &amp;amp;&amp;amp; _objK.checked)&lt;br&gt;   {&lt;br&gt;    for (var d = 0; d &amp;lt; coll.length; d++)&lt;br&gt;    {&lt;br&gt;     var _objD = coll[d];&lt;br&gt;     if (_objD.type == &amp;quot;radio&amp;quot; &amp;amp;&amp;amp; _objD.getAttribute(&amp;quot;name&amp;quot;) == &amp;quot;radio_&amp;quot; + gid + &amp;quot;_d&amp;quot; &amp;amp;&amp;amp; _objD.checked)&lt;br&gt;     {&lt;br&gt;      orList.append(&amp;quot;d_&amp;quot; + _objD.value + &amp;quot;:&amp;quot;);&lt;br&gt;      break;&lt;br&gt;     }&lt;br&gt;    }&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt;  objectList.append(orList.toString() + &amp;quot;;&amp;quot;);&lt;br&gt; }&lt;br&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; JavaScript Code List 2是优化后的代码：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// optimized version&lt;/div&gt;
&lt;div&gt;var functorListEx = new StringBuilder();&lt;br&gt;var objectListEx = new StringBuilder();&lt;br&gt;var coll = document.getElementsByTagName(&amp;quot;INPUT&amp;quot;);&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// regular expression for matching&lt;br&gt;var fnRE = /functor_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}/i;&lt;br&gt;var objRE = /object_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}$/i;&lt;br&gt;var objRE_r = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_r/i;&lt;br&gt;var objRE_a = /object_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_a/i;&lt;br&gt;var objRE_m = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_m/i;&lt;br&gt;var objRE_d = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_d/i;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// helper data structures used by optimized algorithm&lt;br&gt;var aryObjList = new Array();&lt;br&gt;var aryRList = new Array();&lt;br&gt;var aryAList = new Array();&lt;br&gt;var aryMList = new Array();&lt;br&gt;var aryDList = new Array();&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// one pass scan to traverse the nodes collection (coll) to build functorListEx&lt;br&gt;// and intermediate arrays&lt;br&gt;for (var i = 0; i &amp;lt; coll.length; i++)&lt;br&gt;{&lt;br&gt; var _obj = coll[i];&lt;br&gt; if (_obj.type != &amp;quot;checkbox&amp;quot; &amp;amp;&amp;amp; _obj.type != &amp;quot;radio&amp;quot;) continue;&lt;br&gt; var _match;&lt;br&gt; &lt;br&gt; if (_obj.checked &amp;amp;&amp;amp; (_match = _obj.id.match(fnRE)) != null)&lt;br&gt; {&lt;br&gt;  functorListEx.append(_match[0].split(&amp;quot;_&amp;quot;)[1] + &amp;quot;;&amp;quot;);&lt;br&gt; }&lt;br&gt; else if (_obj.checked &amp;amp;&amp;amp; (_match = _obj.name.match(objRE_r)) != null)&lt;br&gt; {&lt;br&gt;  aryRList[_match[0].split(&amp;quot;_&amp;quot;)[1]] = &amp;quot;r_&amp;quot; + _obj.value;&lt;br&gt; }&lt;br&gt; else if (_obj.checked &amp;amp;&amp;amp; (_match = _obj.id.match(objRE_a)) != null)&lt;br&gt; {&lt;br&gt;  aryAList[_match[0].split(&amp;quot;_&amp;quot;)[1]] = &amp;quot;a_&amp;quot;;&lt;br&gt; }&lt;br&gt; else if (_obj.checked &amp;amp;&amp;amp; (_match = _obj.name.match(objRE_m)) != null)&lt;br&gt; {&lt;br&gt;  aryMList[_match[0].split(&amp;quot;_&amp;quot;)[1]] = &amp;quot;m_&amp;quot; + _obj.value;&lt;br&gt; }&lt;br&gt; else if (_obj.checked &amp;amp;&amp;amp; (_match = _obj.name.match(objRE_d)) != null)&lt;br&gt; {&lt;br&gt;  aryDList[_match[0].split(&amp;quot;_&amp;quot;)[1]] = &amp;quot;d_&amp;quot; + obj.value;&lt;br&gt; }&lt;br&gt; else if (_obj.checked &amp;amp;&amp;amp; (_match = _obj.id.match(objRE)) != null)&lt;br&gt; {&lt;br&gt;  aryObjList.push(_match[0].split(&amp;quot;_&amp;quot;)[1]);&lt;br&gt; }&lt;br&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// further process to build objectListEx from the intermediate arrays&lt;br&gt;for (var i = 0; i &amp;lt; aryObjList.length; i++)&lt;br&gt;{&lt;br&gt; var _id = aryObjList[i];&lt;br&gt; var _r = aryRList[_id] == null ? &amp;quot;&amp;quot; : aryRList[_id];&lt;br&gt; var _a = aryAList[_id] == null ? &amp;quot;&amp;quot; : aryAList[_id];&lt;br&gt; var _m = aryMList[_id] == null ? &amp;quot;&amp;quot; : aryMList[_id];&lt;br&gt; var _d = aryDList[_id] == null ? &amp;quot;&amp;quot; : aryDList[_id];&lt;br&gt; objectListEx.append(_id + &amp;quot;:&amp;quot; + _r + &amp;quot;:&amp;quot; + _a + &amp;quot;:&amp;quot; + _m + &amp;quot;:&amp;quot; + _d + &amp;quot;;&amp;quot;);&lt;br&gt;}&lt;br&gt;&lt;/div&gt;
&lt;div&gt;【注】文见&lt;a href="http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!425.entry"&gt;JavaScript代码优化一例（文）&lt;/a&gt;。&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+JavaScript%e4%bb%a3%e7%a0%81%e4%bc%98%e5%8c%96&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!403.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!403.entry</guid><pubDate>Tue, 10 Jul 2007 01:54:50 GMT</pubDate><slash:comments>11</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!403/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!403.entry#comment</wfw:comment><dcterms:modified>2007-08-31T01:16:00Z</dcterms:modified></item><item><title>什么是JSON？</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!327.entry</link><description>&lt;div&gt;前文说到mashups的技术基础时，提到JSON是其中之一，那么什么是JSON？&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;1、定义&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JSON = JavaScript Object Notation，顾名思义，是一种用JavaScript表示（描述）对象的一种方法（记法），D. Crockford在&lt;a href="http://www.ietf.org/rfc/rfc4627.txt?number=4627"&gt;RFC4627&lt;/a&gt;中的定义为：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format.  It was derived from the ECMAScript Programming Language Standard.  JSON defines a small set of formatting rules for the portable representation of structured data.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;1）JSON是一种轻量级的，基于文本的，语言无关的数据交换格式。简单扼要的一句话，就说明了什么是JSON。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;轻量级——与SGML、XML相比较而言，借用JSON作者的话说，是一种&lt;a href="http://www.json.org/fatfree.html"&gt;Fat-Free Alternative to XML&lt;/a&gt;（去掉了XML的脂肪，留下了XML的骨感风韵）。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;基于文本——采用XML的成功作法，而且由于要做“语言无关的数据交换格式”，基于文本是必须的。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;语言无关——虽然是从ECMAScript衍生而来，但由于只采用了ECMAScript中的数据表示法，可以很容易地在其它语言中实现，并非特别绑定于ECMAScript。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;数据交换——由于JSON衍生自程序语言，天生用于描述结构化的数据。而XML由于出自“文档世家”SGML，所以天性适合于描述文档。当然，XML的描述能力比JSON要强，可以描述半结构化数据，而JSON只适合于描述结构化的数据。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;2）是从ECMAScript程序设计语言衍生而来的。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JSON采用了ECMAScript语言的数据（对象、数组以及其它标量数据）表示法。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;3）JSON定义了几条简单的格式化规则用于表示可移植的结构化数据。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;格式化规则体现于下面的语法定义。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;2、语法&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;D. Crockford在&lt;a href="http://www.json.org/"&gt;www.json.org&lt;/a&gt;中给出了JSON的语法定义：&lt;/div&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;i&gt;object&lt;/i&gt; 
&lt;dd&gt;&lt;tt&gt;&lt;b&gt;{}&lt;/b&gt;&lt;/tt&gt;&lt;br&gt;&lt;tt&gt;&lt;b&gt;{&lt;/b&gt;&lt;/tt&gt; &lt;i&gt;members&lt;/i&gt; &lt;tt&gt;&lt;b&gt;}&lt;/b&gt;&lt;/tt&gt; 
&lt;dt&gt;&lt;tt&gt;&lt;b&gt;&lt;/b&gt;&lt;/tt&gt;
&lt;dt&gt;&lt;i&gt;members&lt;/i&gt; 
&lt;dd&gt;&lt;i&gt;pair&lt;/i&gt;&lt;br&gt;&lt;i&gt;pair&lt;/i&gt; &lt;tt&gt;&lt;b&gt;,&lt;/b&gt;&lt;/tt&gt; &lt;i&gt;members&lt;/i&gt; 
&lt;dt&gt;&lt;i&gt;pair&lt;/i&gt; 
&lt;dd&gt;&lt;i&gt;string&lt;/i&gt; &lt;tt&gt;&lt;b&gt;:&lt;/b&gt;&lt;/tt&gt; &lt;i&gt;value&lt;/i&gt; 
&lt;dt&gt;&lt;i&gt;array&lt;/i&gt; 
&lt;dd&gt;&lt;tt&gt;&lt;b&gt;[]&lt;/b&gt;&lt;/tt&gt;&lt;br&gt;&lt;tt&gt;&lt;b&gt;[&lt;/b&gt;&lt;/tt&gt; &lt;i&gt;elements&lt;/i&gt; &lt;tt&gt;&lt;b&gt;]&lt;/b&gt;&lt;/tt&gt; 
&lt;dt&gt;&lt;i&gt;elements&lt;/i&gt; 
&lt;dd&gt;&lt;i&gt;value&lt;/i&gt; &lt;br&gt;&lt;i&gt;value&lt;/i&gt; &lt;tt&gt;&lt;b&gt;,&lt;/b&gt;&lt;/tt&gt; &lt;i&gt;elements&lt;/i&gt; 
&lt;dt&gt;&lt;i&gt;value&lt;/i&gt; 
&lt;dd&gt;&lt;i&gt;string&lt;/i&gt;&lt;br&gt;&lt;i&gt;number&lt;/i&gt;&lt;br&gt;&lt;i&gt;object&lt;/i&gt;&lt;br&gt;&lt;i&gt;array&lt;/i&gt;&lt;br&gt;&lt;tt&gt;&lt;b&gt;true&lt;/b&gt;&lt;/tt&gt;&lt;br&gt;&lt;tt&gt;&lt;b&gt;false&lt;/b&gt;&lt;/tt&gt;&lt;br&gt;&lt;tt&gt;&lt;b&gt;null&lt;/b&gt;&lt;/tt&gt; &lt;/dl&gt;
&lt;p&gt;由此可以看出，JSON的语法特简单！ 
&lt;p&gt;3. 例子 
&lt;p&gt;下面是一个&lt;a href="http://www.json.org/example.html"&gt;D. Crockford给出的例子&lt;/a&gt;： 
&lt;p&gt;{&lt;br&gt;    &amp;quot;glossary&amp;quot;: {&lt;br&gt;        &amp;quot;title&amp;quot;: &amp;quot;example glossary&amp;quot;,&lt;br&gt;        &amp;quot;GlossDiv&amp;quot;: {&lt;br&gt;            &amp;quot;title&amp;quot;: &amp;quot;S&amp;quot;,&lt;br&gt;            &amp;quot;GlossList&amp;quot;: {&lt;br&gt;                &amp;quot;GlossEntry&amp;quot;: {&lt;br&gt;                    &amp;quot;ID&amp;quot;: &amp;quot;SGML&amp;quot;,&lt;br&gt;                    &amp;quot;SortAs&amp;quot;: &amp;quot;SGML&amp;quot;,&lt;br&gt;                    &amp;quot;GlossTerm&amp;quot;: &amp;quot;Standard Generalized Markup Language&amp;quot;,&lt;br&gt;                    &amp;quot;Acronym&amp;quot;: &amp;quot;SGML&amp;quot;,&lt;br&gt;                    &amp;quot;Abbrev&amp;quot;: &amp;quot;ISO 8879:1986&amp;quot;,&lt;br&gt;                    &amp;quot;GlossDef&amp;quot;: {&lt;br&gt;                        &amp;quot;para&amp;quot;: &amp;quot;A meta-markup language, used to create markup languages such as DocBook.&amp;quot;,&lt;br&gt;                        &amp;quot;GlossSeeAlso&amp;quot;: [&amp;quot;GML&amp;quot;, &amp;quot;XML&amp;quot;]&lt;br&gt;                    },&lt;br&gt;                    &amp;quot;GlossSee&amp;quot;: &amp;quot;markup&amp;quot;&lt;br&gt;                }&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;} 
&lt;p&gt;&lt;br&gt;其等价的XML表示为： 
&lt;p&gt;&lt;br&gt; &lt;br&gt; &lt;br&gt;  &lt;br&gt;  &lt;br&gt;   &lt;br&gt;    SGML&lt;br&gt;    SGML&lt;br&gt;    Standard Generalized Markup Language&lt;br&gt;    &lt;acronym&gt;SGML&lt;/acronym&gt;&lt;br&gt;    ISO 8879:1986&lt;br&gt;    &lt;br&gt;     A meta-markup language, used to create markup languages such as DocBook.&lt;br&gt;     SGML&lt;br&gt;     XML&lt;br&gt;    &lt;br&gt;    markup&lt;br&gt;   &lt;br&gt;  &lt;br&gt; &lt;br&gt;
&lt;p&gt;注：这个XML表示是我从JSON表示中推出的，与D. Crockford给出的XML表示有所不同。&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+%e4%bb%80%e4%b9%88%e6%98%afJSON%ef%bc%9f&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!327.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!327.entry</guid><pubDate>Mon, 12 Mar 2007 17:40:00 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!327/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!327.entry#comment</wfw:comment><dcterms:modified>2007-05-23T15:41:58Z</dcterms:modified></item><item><title>JavaScript学习笔记（之三）</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!298.entry</link><description>&lt;div&gt;已经很久没有抬头看看天了，偶一抬头，发现天上彩云飘飘：Unobtrusive scripting，Prototype-based languages，Mixin，Closures……&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Unobtrusive scripting已经在笔记之一里做了描述，此处不赘。Mixin和Closures以后再慢慢道来，下面来看看何谓Prototype-based languages？&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;我们被教导了多年的OO，脑子里塞满了class, object, inheritance, polymorphism, encapsulation, abstract, virtual，等等，等等。现在看来，这些都已经是classic OO language的特征了，此种语言可以被概括为Class-based language。除此之外，还有一种模式的OO language，称为Prototype-based language。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;说也奇怪，老外总是有创造新语言的强烈冲动（相比之下，由于我们对语言本质没有深入的研究，所以难有创见！大家都忙着挣钱呢……^_^）。稍微搜索一下，发现N多的&lt;a href="http://www.dekorte.com/docs/protos/"&gt;Prototype-based languages&lt;/a&gt;，典型者除JavaScript之外，有Self，NewtonScript，Io，等等。其中：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Self：&lt;/div&gt;
&lt;div&gt;Self is an object-oriented language for exploratory programming based on a small number of simple and concrete ideas: prototypes, slots, and behavior. Prototypes combine inheritance and instantiation to provide a framework that is simpler and more flexible than most object-oriented languages. Slots unite variables and procedures into a single construct. This permits the inheritance hierarchy to take over the function of lexical scoping in conventional languages. Finally, because Self does not distinguish state from behavior, it narrows the gaps between ordinary objects, procedures, and closures. Self's simplicity and expressiveness offer new insights into object-oriented computation. &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;NewtonScript：&lt;/div&gt;
&lt;div&gt;NewtonScript, developed for the Apple Newton PDA platform, is a prototype-based programming language. Rather than two levels of abstraction, class and object, there is just one, the object. Major design goals of the language were small memory consumption of the created programs and the ability to easily program graphical user interfaces. Both are well met by prototype-based languages. A third design goal, good learnability, was attained by an easy syntax. &lt;/div&gt;
&lt;div&gt;&lt;em&gt;&lt;/em&gt; &lt;/div&gt;
&lt;div&gt;Io：&lt;/div&gt;
&lt;div&gt;Io is a small, prototype-based programming language. The ideas in Io are mostly inspired by Smalltalk (all values are objects), Self (prototype-based), NewtonScript (differential inheritance), Act1 (actors and futures for concurrency), LISP (code is a runtime inspectable/modifiable tree) and Lua (small, embeddable). &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;看来各有千秋，而且Io似乎有点集大成的味道——集各语言特点于一身。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;这些语言此处暂且按下不表，继续我们的话题——prototype-based languages。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Prototype的字典解释：first or original example of sth that has been or will be copied or developed; model or preliminary version。中文可以解释为：原型，雏形，模型，蓝本。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Prototype-based languages are object oriented langauges where a new object instance is &amp;quot;cloned&amp;quot; from existing live object(a prototype) instead of being constructed by a class. This makes the language simpler by requiring one less data type and solving the infinite regress problem of classes (if you use a class to create an object, what do you use to create a class?). It is also ideal for systems such as GUIs where the pattern of creating one object by copying and modifying another is already handled by the language itself. &lt;/div&gt;
&lt;div&gt;基于原型的语言是面向对象语言，其中新的对象实例是从已存在的活动对象（即原型）“克隆”而得，而不是从类构造得来的。这使得基于原型的语言更简单，因为少了一种数据类型，而且也解决了类的无穷回溯问题（如果用类来创建对象，那用什么来创建类呢？）。这种语言特别适合于像GUI这样的系统，因为通过拷贝及修改另一个对象而创建一个新对象的模式已经由语言本身处理了。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;定义总是让人头大，下面我们Learn by Example：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;考虑雇员与管理者这样的两级系统，一般来说，管理者属于雇员，但雇员却不一定属于管理者。借用经典OO的术语，如果将雇员定义为基类或超类（base class or superclass）的话，那管理者就是雇员的导出类或子类（derived class or subclass），那么如何在JavaScript中定义这种层次关系呢？&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// 基类的构造函数&lt;/div&gt;
&lt;div&gt;function Employee(name, dept)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;        this.name = name;&lt;/div&gt;
&lt;div&gt;        this.dept = dept;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;// 子类的构造函数&lt;/div&gt;
&lt;div&gt;function Manager(name, dept)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;        Employee.call(this, name, dept);          // 基类的实例化&lt;/div&gt;
&lt;div&gt;        this.isManager = true;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Manager.prototype = new Employee();      // 此语句建立关系：Manager is a subclass of Employee&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;var empA = new Employee(&amp;quot;David&amp;quot;, &amp;quot;Development&amp;quot;);&lt;/div&gt;
&lt;div&gt;var mgrB = new Manager(&amp;quot;Bill&amp;quot;, &amp;quot;Development&amp;quot;);&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;alert(empA.name);            // 显示David&lt;/div&gt;
&lt;div&gt;alert(empA.isManager);      // 显示undefined，因为empA没有isManager属性&lt;/div&gt;
&lt;div&gt;alert(mgrB.name);             // 显示Bill，name为mgrB的继承属性&lt;/div&gt;
&lt;div&gt;alert(mgrB.isManager);       // 显示true，mgrB有isManager属性，且其值为true&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Employee和Manager即实现了OOPL的典型特征：继承（inheritance）。这种继承关系是通过prototype对象实现的（Manager.prototype = new Employee();），故称为基于prototype的继承（prototype-based inheritance），而经典OOPL的继承是通过class实现的，称为class-based inheritance。&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+JavaScript%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0%ef%bc%88%e4%b9%8b%e4%b8%89%ef%bc%89&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!298.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!298.entry</guid><pubDate>Mon, 15 Jan 2007 16:41:30 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!298/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!298.entry#comment</wfw:comment><dcterms:modified>2007-01-15T17:32:35Z</dcterms:modified></item><item><title>JavaScript学习笔记（之二）</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!296.entry</link><description>&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;JavaScript——世界上误解最深的程序设计语言&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;译注：本文译自Douglas Crockford的《&lt;a href="http://javascript.crockford.com/javascript.html"&gt;JavaScript:The World's Most Misunderstood Programming Language&lt;/a&gt;》，是难得一见的好文！&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript（也被成为Mocha，LiveScript，JScript，ECMAScript）是世界上最流行（most popular）的程序设计语言之一。基本上每台PC都至少有一个JavaScript解释器在运行，这要归功于JavaScript是Web的脚本语言。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;除了其流行之外，很少有人知道JavaScript还是一种非常优美的、动态的、面向对象的、通用的程序设计语言。这怎么会成为一个秘密？这种语言为什么会被如此误解？&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;名字&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;Java-前缀使人认为JavaScript多少与Java有关系，是Java的子集或缩减功能后的版本。似乎这个名字是有意用来制造混淆，且从混淆产生误解。实际上，JavaScript并不是Java的解释版本，Java是Java，JavaScript是一种不同的语言。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript在语法上类似于Java，就像Java类似于C一样。JavaScript是Java的子集并不比Java是C的子集多什么东西。JavaScript比Java能更好地应用于Java（当时称为Oak）原初的设计目的。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript并不是在Sun Microsystems公司开发的，而是在Netscape。当初叫LiveScript，如果叫这个名字，就不会产生如此多的误解。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;-Script后缀会使人认为不是一种实际的（real）程序设计语言，会认为脚本语言在功能上比程序设计语言差很多。但这实际上是特化问题（a matter of specialization，可能是指JavaScript只是专注于某些领域或在某些方面有特长——译注），与C相比，JavaScript在性能和表达能力及活力（dynamism）上取得了一种平衡。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;穿着C的衣服的Lisp&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript类似于C的语法，包括花括号（{}）以及重量级的（clunky）for语句，使其看起来与通常的过程语言没什么不同。实际上这是误导，因为与C或Java比起来，JavaScript与函数式语言如Lisp或Scheme具有更多的共同点。JavaScript用数组代替了列表（lists），用对象代替了属性列表（property lists），函数是第一级别的（first class），而且JavaScript具有closures（closures与lambda表达式有关，将在以后展开来谈——译注），用不着平衡所有那些括号就可以得到lambda表达式（You get lambdas without having to balance all those parens.——译注：虽然翻出来了，但意思还是不太明白，是指与Lisp相比吗？Lisp确实要balance all those parens）。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;擅长角色（Typecasting）&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;JavaScript是被设计来运行于Netscape Navigator浏览器中的，它的成功使其成为所有浏览器的标准配置，这倒成了JavaScript所擅长的角色。实际上JavaScript是程序设计语言中的George Reeves（美国演员，饰演电视系列剧《超人历险记》中的超人——译注），它能很好地适用于一大类的非Web应用程序。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;目标游移（Moving Target）&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;JavaScript初始的几个版本功能非常弱，缺少异常处理，内函数（inner functions），以及继承。目前它已经是一个完全的面向对象的程序设计语言。但对于该语言的很多意见都集中于其不成熟的形式。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;ECMA委员会（JavaScript语言的管理者）正在开发各种扩展，但这些扩展会更加恶化其最大的问题：它已经有太多的版本了。版本太多不可避免会产生混淆。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;设计错误&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;没有一种程序语言是完善的。JavaScript同样有设计错误，如重载+操作符，通过强制类型转换，使其用于加法和字符串连接，以及容易产生错误的with语句。保留字策略限制太严，分号插入（semicolon insertion），与直接量的正则表达式记法一样，是一个巨大的错误。这些错误已经导致了各种各样的程序设计错误。语言的设计作为一个整体已经使人产生怀疑。幸好，这些问题可以通过一个很好的lint程序得到缓解。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;语言的设计在整体上还是很合理的，奇怪的是，ECMA委员会似乎对改正这些问题并没有兴趣，或许他们对制造新的问题兴趣更大。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;极坏的实现&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript的几个早期实现充满了缺陷（quite buggy），这对语言影响很坏，而且这些实现又嵌入在可怕的缺陷多多的Web浏览器里。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;坏的书籍&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;几乎所有关于JavaScript的书都很糟糕，有错误，低劣的例子，并倡导一些不好的实践。语言的重要特性经常被低劣地解释，或整个忽略掉了。我看了很多JavaScript的书，只推荐一本：David Flanagan的《JavaScript: The Definitive Guide (5th Edition)》。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;不够标准的标准&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;ECMA出版JavaScript语言的官方规范，可这个规范的质量却极为低劣。难读难懂（难怪我读不懂，现在看来是可以原谅的:)——译注）！这是产生上述坏书问题的一个原因，因为作者无法用标准文档改进他们对语言的理解。ECMA和TC39委员会应该很尴尬。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;业余爱好者&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;许多写JavaScript程序的人都不是程序员，他们对如何写好的程序缺乏训练。JavaScript具有很强的表达能力，他们怎么写都可以做点有用的事情，这造成了JavaScript只适用于业余爱好者，而不适合专业程序员的形象。事实当然不是。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;面向对象&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript是面向对象的吗？它有包含数据的对象以及处理数据的方法，对象可以包含其它的对象。它没有类，但有构造函数，能起到类的作用，如作为类变量和类方法的容器。没有面向类的继承（class-oriented inheritance），但有面向原型的继承（prototype-oriented inheritance）。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;构建对象系统的两种主要方式，一是通过继承（is-a），一是通过聚集（has-a），JavaScript两种方式都有，其动态特性使其在聚集方面更优秀。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;一些人会争辩，说JavaScript并非真正面向对象，因为不能提供信息隐藏，也就是说，对象没有私有变量和私有方法，所有成员都是公共的。但JavaScript的对象可以有私有变量和私有方法，当然，很少人理解，因为JavaScript是世界上误解最深的语言。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;一些人会争辩，说JavaScript并非真正面向对象，因为不提供继承。但JavaScript不仅提供经典的继承，也提供其它的代码重用模式。&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+JavaScript%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0%ef%bc%88%e4%b9%8b%e4%ba%8c%ef%bc%89&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!296.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!296.entry</guid><pubDate>Sat, 13 Jan 2007 16:26:29 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!296/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!296.entry#comment</wfw:comment><dcterms:modified>2007-01-13T17:20:12Z</dcterms:modified></item><item><title>JavaScript学习笔记（之一）</title><link>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!293.entry</link><description>&lt;div&gt;曾跟朋友们笑谈：写程序这么多年，现在最看不懂的程序是JavaScript！&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;JavaScript何方神圣？非也，just an interpreted scripting language！如此“卑微”，何言“看不懂”？&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;其实，看不懂的并不是JavaScript程序，而是lambda表达式！JavaScript虽然“卑微”，却有着“高贵”的理论背景——lambda演算，这是一个需要深入研究的领域，此处按下不表。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;最近读了很多关于JavaScript的资料，有一个词频频出现：Unobtrusive Scripting。查字典，obtrude = force (oneself, one's opinions, ideas, etc) upon sb/sth, esp when unwanted. 所以，Unobtrusive可以解释为“不强加于人的，优雅的，温和的，君子的”。那么，为什么现在会强调Unobtrusive Scripting呢？&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;这与长期以来的“不良习惯”有关系：&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;1、由于DHTML的影响，Scripters已经习惯于“粗暴”地对待HTML Elements。&lt;/div&gt;
&lt;div&gt;例：&lt;/div&gt;
&lt;div&gt;function setBkColor(o, color)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;    o.style.backgroundColor = color;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt;从Unobtrusive的观点来看，这不是一个好的方式，因为假如对象o不存在，就会导致JavaScript出错。Unobtrusive的方式应该是：&lt;/div&gt;
&lt;div&gt;function setBkColor(o, color)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;    if (o) o.style.backgroundColor = color;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt;而且DHTML已经是一种过时的（outdated）技术，应该使用DOM Scripting。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;2、由于IE的强势影响，Scripters没有考虑浏览器的兼容性。&lt;/div&gt;
&lt;div&gt;例：&lt;/div&gt;
&lt;div&gt;function setBkColor(color)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;    document.all.o.style.backgroundColor = color;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt;document.all是一个IE所支持的属性，其它浏览器并不支持，所以在其它浏览器中就会出错。而且通过document.all和document.layer来判断浏览器类型也已经过时了，Unobtrusive的方式应该是：&lt;/div&gt;
&lt;div&gt;function setBkColor(color)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;    var o = document.getElementById('elementId');&lt;/div&gt;
&lt;div&gt;    if (o) o.style.backgroundColor = color;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;3、由于JavaScript的“卑微”，使得Scripters很“随意”地将大量JavaScript代码散落在HTML页面中（尤其是heavily-scripted页面）。Unobtrusive强调将HTML代码、CSS代码、JavaScript代码分离：&lt;/div&gt;
&lt;div&gt;HTML代码——什么内容（content）&lt;/div&gt;
&lt;div&gt;CSS代码——如何显示出来（display）&lt;/div&gt;
&lt;div&gt;JavaScript代码——呈现什么样的行为（behavior）&lt;/div&gt;
&lt;div&gt;呵呵，这三者好象有点MVC的味道！&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;4、内容的可访问性（Web Content Accessibility）&lt;/div&gt;
&lt;div&gt;HTML Elements的行为表示为鼠标/键盘事件，但很少有Scripters会考虑用户没有鼠标的情况。W3C发布了一个Web Content Accessibility Guidelines，建议使用不依赖于设备的事件处理程序，如果必须使用依赖于设备的处理程序的话，尽量提供冗余的输入机制，如同时支持鼠标和键盘（&amp;quot;onmousedown&amp;quot;与&amp;quot;onkeydown&amp;quot;，&amp;quot;onmouseup“与&amp;quot;onkeyup&amp;quot;，&amp;quot;onclick&amp;quot;与&amp;quot;onkeypress&amp;quot;等）。&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;由以上的简单介绍可以看出，Unobtrusive Scripting确实是一种“不强加于人的，优雅的，温和的，君子的”程序开发方式。&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-1537263819930693984&amp;page=RSS%3a+JavaScript%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0%ef%bc%88%e4%b9%8b%e4%b8%80%ef%bc%89&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=prowyh.spaces.live.com&amp;amp;GT1=prowyh"&gt;</description><comments>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!293.entry#comment</comments><guid isPermaLink="true">http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!293.entry</guid><pubDate>Thu, 11 Jan 2007 18:04:23 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!293/comments/feed.rss</wfw:commentRss><wfw:comment>http://prowyh.spaces.live.com/Blog/cns!EAAA8AB356F88EA0!293.entry#comment</wfw:comment><dcterms:modified>2007-01-12T11:27:54Z</dcterms:modified></item></channel></rss>