<?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>YY in Limbo 混沌海狂想 &#187; JavaScript</title>
	<atom:link href="http://www.limboy.com/category/coder/js/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.limboy.com</link>
	<description>这里既空虚又充实，没有规则，没有约束，创造来自思考，生存依赖想像，现实源自梦想</description>
	<lastBuildDate>Fri, 07 Oct 2011 19:33:20 +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>从事件驱动到observable的异步编程——PubSub+Promise+Rx的JS事件库</title>
		<link>http://www.limboy.com/2011/09/25/pubsub-plus-promise-plus-rx/</link>
		<comments>http://www.limboy.com/2011/09/25/pubsub-plus-promise-plus-rx/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 15:35:39 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[代码]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=463</guid>
		<description><![CDATA[你上当叻，虽然从外面看标题很有气势，传达出一种宏大叙事的赶脚，其实我只是刚刚把一个阿尔法城的JS模块提交到github，想顺便介绍一下，但我连API文档都懒得写，就别指望能深入浅出的讲一遍来龙去脉了⋯⋯


所以就直接帖几个前置阅读的链接罢！
这些潮流的外部起源：（技术也有外源论/exogenesis⋯⋯）
Twisted（Python的事件驱动异步引擎）里的Deferred模式
微软推崇的Reactive Extensions (Rx)
虽然我是微软黑但微软网站上的这两篇推介文章不错：
Understanding the Publish/Subscribe Pattern for Greater JavaScript Scalability
Asynchronous Programming in JavaScript with “Promises”
应该都有人翻译了，比如这个：infoQ: JavaScript异步编程的Promise模式
jQuery早就跟微软一个鼻孔出气了：
http://api.jquery.com/category/deferred-object/
CommonJS的Promises提案，照例又分了好多种ABCD神马的：
http://wiki.commonjs.org/wiki/Promises
假如你愿意这里还有一篇paper⋯⋯

阿尔法城的客户端程序里有一个叫作event的模块提供了以上提到的PubSub模式、Promise模式和部分Rx模式，可以算是OzJS的核心module。
就像名字一样，它的初衷是一个最基础最简洁的消息事件库，类似nodejs的EventEmitter。在项目实践中，我很早就注意到可以用统一的事件机制实现Twisted风格的API，为此需要能随时提取事件主题（本质上就是promise对象），后来又根据实际需求加入了能表示状态转移的触发器（enable/resolve）和“一次性”的侦听器（wait/then），最后实现了同时依赖多个异步事件（或promise）的语法工具，包括并发事件（when）和有先后顺序的事件流（follow和end）。所以这个模块不是基于自顶向下的设计，而是在逐步的实践、hack和验证中发展出来的，上面提到的各种模式词汇都是“事后美化”，我觉得大多数“设计模式”也是这样——是对实践方法的归纳和描述，而不是在实践中套用的“新技术”。

开始帖使用范例～

把Event实例单独定义为模块，承担应用各模块之间的消息传递：
oz.def(&#34;notify&#34;, [&#34;event&#34;], function(Event){
&#160; &#160; return&#160;Event(); // 以下例子里省略def/require声明，继续沿用notify和Event这两个局部变量名
});
为基础类生成独立的事件命名空间，不依赖应用级的全局事件：
Dialog.prototype = {
&#160; &#160; init: function(opt){
&#160; &#160; &#160; &#160; this.event = Event();
&#160; &#160; },
&#160; &#160; update: function()&#160;{
&#160; &#160; &#160; &#160; this.updateSize();
&#160; &#160; &#160; &#160; this.updatePosition();
&#160; &#160; &#160; &#160; this.event.fire(&#34;update&#34;, [this]);
&#160; &#160; &#160; &#160; return&#160;this;
&#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://promotejs.com/" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/09/event_18289736.jpeg" style="float:left;margin:0 10px 10px 0;" /></a>你上当叻，虽然从外面看标题很有气势，传达出一种宏大叙事的赶脚，其实我只是刚刚把一个<a target="_blank" href="http://alphatown.com">阿尔法城</a>的JS模块提交到github，想顺便介绍一下，但我连API文档都懒得写，就别指望能深入浅出的讲一遍来龙去脉了⋯⋯<br />
<span id="more-463"></span></p>
<div style="clear:left;"></div>
<p>所以就直接帖几个前置阅读的链接罢！</p>
<p>这些潮流的外部起源：（技术也有外源论/exogenesis⋯⋯）<br />
<a target="_blank" href="http://twistedmatrix.com/documents/current/core/howto/defer.html">Twisted（Python的事件驱动异步引擎）里的Deferred模式</a><br />
<a target="_blank" href="http://msdn.microsoft.com/en-us/data/gg577609">微软推崇的Reactive Extensions (Rx)</a></p>
<p>虽然我是微软黑但微软网站上的这两篇推介文章不错：<br />
<a target="_blank" href="http://msdn.microsoft.com/en-us/scriptjunkie/hh201955">Understanding the Publish/Subscribe Pattern for Greater JavaScript Scalability</a><br />
<a target="_blank" href="http://blogs.msdn.com/b/ie/archive/2011/09/11/asynchronous-programming-in-javascript-with-promises.aspx">Asynchronous Programming in JavaScript with “Promises”</a><br />
应该都有人翻译了，比如这个：<a target="_blank" href="http://www.infoq.com/cn/news/2011/09/js-promise">infoQ: JavaScript异步编程的Promise模式</a></p>
<p>jQuery早就跟微软一个鼻孔出气了：<br />
<a target="_blank" href="http://api.jquery.com/category/deferred-object/">http://api.jquery.com/category/deferred-object/</a></p>
<p>CommonJS的Promises提案，照例又分了好多种ABCD神马的：<br />
<a  target="_blank" href="http://wiki.commonjs.org/wiki/Promises">http://wiki.commonjs.org/wiki/Promises</a></p>
<p><a  target="_blank" href="http://www.cs.brown.edu/%7Esk/Publications/Papers/Published/mgbcgbk-flapjax/">假如你愿意这里还有一篇paper</a>⋯⋯<br />
<br/></p>
<p>阿尔法城的<a  target="_blank" href="http://www.limboy.com/2011/07/10/mvc-behind-alphatown/">客户端程序</a>里有一个叫作<a  target="_blank" href="https://github.com/dexteryy/OzJS/blob/master/mod/event.js">event</a>的模块提供了以上提到的PubSub模式、Promise模式和部分Rx模式，可以算是<a  target="_blank" href="https://github.com/dexteryy/OzJS">OzJS</a>的核心module。</p>
<p>就像名字一样，它的初衷是一个最基础最简洁的消息事件库，类似nodejs的EventEmitter。在项目实践中，我很早就注意到可以用统一的事件机制实现Twisted风格的API，为此需要能随时提取事件主题（本质上就是promise对象），后来又根据实际需求加入了能表示状态转移的触发器（enable/resolve）和“一次性”的侦听器（wait/then），最后实现了同时依赖多个异步事件（或promise）的语法工具，包括并发事件（when）和有先后顺序的事件流（follow和end）。所以这个模块不是基于自顶向下的设计，而是在逐步的实践、hack和验证中发展出来的，上面提到的各种模式词汇都是“事后美化”，我觉得大多数“设计模式”也是这样——是对实践方法的归纳和描述，而不是在实践中套用的“新技术”。<br />
<br/><br />
开始帖使用范例～<br />
<br/></p>
<p>把Event实例单独定义为模块，承担应用各模块之间的消息传递：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">oz</span><span style="color: Gray;">.</span><span style="color: Blue;">def</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">notify</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">event</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">Event</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Event</span><span style="color: Olive;">()</span><span style="color: Gray;">; </span><span style="color: #ffa500;">// 以下例子里省略def/require声明，继续沿用notify和Event这两个局部变量名</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>为基础类生成独立的事件命名空间，不依赖应用级的全局事件：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">Dialog</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">init</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">opt</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">event</span><span style="color: Gray;"> = </span><span style="color: Blue;">Event</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">update</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">()</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">updateSize</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">updatePosition</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">event</span><span style="color: Gray;">.</span><span style="color: Blue;">fire</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">update</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Green;">this</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">this</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li></ol></div>
<p>监听消息和解除监听：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">bind</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">msg:A</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">msg</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Blue;">msg</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">unbind</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">msg:A</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>发送消息：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">setTimeout</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">fire</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">msg:A</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">hey jude</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Maroon;">1000</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li></ol></div>
<p>状态转移：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Gray;">$</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">#button1</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">click</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">e</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">resolve</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">button1:clicked</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Green;">this</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">bind</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">button1:clicked</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">button</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// 按钮1已经点击过，所以立刻执行</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">button</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">color</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">'</span><span style="color: Red;">black</span><span style="color: #8b0000;">'</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">bind</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">button1:clicked</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">button</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">// 等待按钮1点击之后再执行</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">button</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">color</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">'</span><span style="color: Red;">red</span><span style="color: #8b0000;">'</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>异步回调：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">data</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">load</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">url</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; $.</span><span style="color: Blue;">getJSON</span><span style="color: Olive;">(</span><span style="color: Blue;">url</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">resolve</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">data:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> + </span><span style="color: Blue;">url</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Blue;">json</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">else</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">reject</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">data:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> + </span><span style="color: Blue;">url</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">promise</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">data:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> + </span><span style="color: Blue;">url</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">data</span><span style="color: Gray;">.</span><span style="color: Blue;">load</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">jsonp_data_1.js</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">// json callback</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">// json error </span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>也可以用自己的promise对象：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">promise</span><span style="color: Gray;"> = </span><span style="color: Blue;">Event</span><span style="color: Gray;">.</span><span style="color: Blue;">Promise</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">$.</span><span style="color: Blue;">ajax</span><span style="color: Olive;">({</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">url</span><span style="color: Gray;">: </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">jsonp_data_1.js</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">success</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">promise</span><span style="color: Gray;">.</span><span style="color: Blue;">resolve</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">promise</span><span style="color: Gray;">.</span><span style="color: Blue;">fire</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">json loaded</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">error</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">promise</span><span style="color: Gray;">.</span><span style="color: Blue;">reject</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">promise</span><span style="color: Gray;">.</span><span style="color: Blue;">error</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">json error</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: #ffa500;">// fire和error都会执行bind的参数，resolve执行then和bind，所以bind的参数会被执行2次</span></li>
<li><span style="color: #ffa500;">// 如果ajax请求在之前已经返回，则只有then或fail的参数会被执行（因为他们监听的是“状态改变”）</span></li>
<li><span style="color: Blue;">promise</span><span style="color: Gray;">.</span><span style="color: Blue;">bind</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){})</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){})</span><span style="color: Gray;">.</span><span style="color: Blue;">fail</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){})</span><span style="color: Gray;">;</span></li></ol></div>
<p>事件流：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">promise</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">data:jsonp_data_1.js</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">setTimeout</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">resolve</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">delay:1000</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Gray;">+</span><span style="color: Green;">new</span><span style="color: Gray;">&nbsp;</span><span style="color: Teal;">Date</span><span style="color: Olive;">()</span><span style="color: Gray;">, </span><span style="color: Blue;">json</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Maroon;">1000</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">promise</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">delay:1000</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">.</span><span style="color: Blue;">follow</span><span style="color: Olive;">()</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">time</span><span style="color: Gray;">, </span><span style="color: Blue;">json</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">setTimeout</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">console</span><span style="color: Gray;">.</span><span style="color: Blue;">log</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">[数据在3秒前加载成功]</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">json</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Maroon;">2000</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">.</span><span style="color: Blue;">end</span><span style="color: Olive;">()</span><span style="color: Gray;">.</span><span style="color: Blue;">fail</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">msg</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">promise</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">data:error</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">resolve</span><span style="color: Olive;">([</span><span style="color: Blue;">msg</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">.</span><span style="color: Blue;">follow</span><span style="color: Olive;">()</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">console</span><span style="color: Gray;">.</span><span style="color: Blue;">log</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">[数据加载失败]</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">msg</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>避免多层的回调嵌套（“callback hell”）：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">fs</span><span style="color: Gray;"> = </span><span style="color: Blue;">require</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">fs</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">fs</span><span style="color: Gray;">.</span><span style="color: Blue;">readFile</span><span style="color: Olive;">(</span><span style="color: Blue;">input</span><span style="color: Gray;">, </span><span style="color: #8b0000;">'</span><span style="color: Red;">utf-8</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">err</span><span style="color: Gray;">, </span><span style="color: Blue;">data</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">beautifuldata</span><span style="color: Gray;"> = </span><span style="color: Blue;">js_beautify</span><span style="color: Olive;">(</span><span style="color: Blue;">data</span><span style="color: Gray;">, </span><span style="color: Blue;">options</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">// 需要修改readFile和writeFile传出promise对象</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fs</span><span style="color: Gray;">.</span><span style="color: Blue;">writeFile</span><span style="color: Olive;">(</span><span style="color: Blue;">output</span><span style="color: Gray;">, </span><span style="color: Blue;">beautifuldata</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">.</span><span style="color: Blue;">follow</span><span style="color: Olive;">()</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">err</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">err</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">throw</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">err</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">console</span><span style="color: Gray;">.</span><span style="color: Blue;">log</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">Success!</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>依赖多个并发事件：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">when</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">msg:A</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">msg:B</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">jsonp:A</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">jsonp:B</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: #ffa500;">// when传出新的promise对象</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; .</span><span style="color: Blue;">some</span><span style="color: Olive;">(</span><span style="color: Maroon;">3</span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span><span style="color: #ffa500;">// 如果不调用some或any，默认为全部事件完成后再触发resolve </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; .</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span><span style="color: Gray;">&nbsp;</span><span style="color: #ffa500;">// 已经取到3/4的数据，参数顺序跟when的参数顺序一样</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">console</span><span style="color: Gray;">.</span><span style="color: Blue;">warn</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">recieve 3/4</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>静态方法Event.when接受promise参数，可以写出更复杂的依赖关系：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">Event</span><span style="color: Gray;">.</span><span style="color: Blue;">when</span><span style="color: Olive;">(</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">when</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">msg:A</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">msg:B</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">, </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">when</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">click:btn1</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">clicked:btn2</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">any</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">then</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">args1</span><span style="color: Gray;">, </span><span style="color: Blue;">args2</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">// 相当于：&quot;msg:A&quot; &amp;&amp; &quot;msg:B&quot; &amp;&amp; ( &quot;click:btn1&quot; || &quot;clicked:btn2&quot; )</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">console</span><span style="color: Gray;">.</span><span style="color: Blue;">warn</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">recieve all messages, click one button</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p><br/><br />
测试demo：<a  target="_blank" href="https://github.com/dexteryy/OzJS/blob/master/tests/test_event.html">https://github.com/dexteryy/OzJS/blob/master/tests/test_event.html</a><br />
可以在console里观察执行顺序⋯⋯</p>
<p>从这个测试页可以看出我连单元测试都懒得写⋯⋯<br />
<br/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2011/09/25/pubsub-plus-promise-plus-rx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《新版阿尔法城背后的前端MVC实践》的幻灯片和⋯⋯这次没剧本⋯⋯</title>
		<link>http://www.limboy.com/2011/07/10/mvc-behind-alphatown/</link>
		<comments>http://www.limboy.com/2011/07/10/mvc-behind-alphatown/#comments</comments>
		<pubDate>Sun, 10 Jul 2011 03:16:25 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[web服务/应用]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[豆瓣]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=441</guid>
		<description><![CDATA[拖到最后一天才开始准备，所以没时间写剧本照着念了T___T
幻灯片上的吐槽跟实际的讲话其实是属于两个平行世界：
http://www.slideshare.net/dexter_yy/mvc-8554206
 新版阿尔法城背后的前端MVC实践 
 View more presentations from Dexter Yy 

精选几张梗：





]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.limboy.com/wp-content/uploads/2010/12/0ee4f2b61c1d5d96b31343480a1110bf-bpfull.jpg" alt="" title="key" width="150" height="150" style="float:left;margin:0 5px 5px 0;"  />拖到最后一天才开始准备，所以没时间写剧本照着念了T___T</p>
<p>幻灯片上的吐槽跟实际的讲话其实是属于两个平行世界：<span id="more-441"></span></p>
<p><a href="http://www.slideshare.net/dexter_yy/mvc-8554206">http://www.slideshare.net/dexter_yy/mvc-8554206</a></p>
<div style="width:425px" id="__ss_8554206"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/dexter_yy/mvc-8554206" title="新版阿尔法城背后的前端MVC实践" target="_blank">新版阿尔法城背后的前端MVC实践</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/8554206" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/dexter_yy" target="_blank">Dexter Yy</a> </div>
</p></div>
<p>精选几张梗：</p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown.jpeg"><img src="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-1024x767.jpg" alt="" title="mvc-behind-alphatown" style="width:500px" class="alignnone size-large wp-image-442" /></a></p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-2.jpeg"><img src="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-2-1024x767.jpg" alt="" title="mvc-behind-alphatown copy 2" style="width:500px"  class="alignnone size-large wp-image-443" /></a></p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-3.jpeg"><img src="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-3-1024x767.jpg" alt="" title="mvc-behind-alphatown copy 3" style="width:500px" class="alignnone size-large wp-image-444" /></a></p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-4.jpeg"><img src="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-4-1024x767.jpg" alt="" title="mvc-behind-alphatown copy 4" style="width:500px" class="alignnone size-large wp-image-445" /></a></p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-5.jpeg"><img src="http://www.limboy.com/wp-content/uploads/2011/07/mvc-behind-alphatown-copy-5-1024x767.jpg" alt="" title="mvc-behind-alphatown copy 5"  style="width:500px"  class="alignnone size-large wp-image-446" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2011/07/10/mvc-behind-alphatown/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>《编程人生》的读书笔记：Brendan Eich章节里关于JS语言改进的内容</title>
		<link>http://www.limboy.com/2011/04/23/brendan-eich-in-codersatwork/</link>
		<comments>http://www.limboy.com/2011/04/23/brendan-eich-in-codersatwork/#comments</comments>
		<pubDate>Sat, 23 Apr 2011 09:23:38 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=383</guid>
		<description><![CDATA[这篇是之前发在豆瓣读书笔记里的内容。其他更零碎的东西就不搬运过来了，平时都发在google reader note和豆瓣日记/推荐里~
JavaScript用户的斯德哥尔摩综合症：微软不想改进，所以这语言也就这样了，用lambda代码来实现所有东西是一个优势，干嘛还要更好的语法
&#8220;Oh, it only does what it does because Microsoft stopped letting it improve, so why should we want better syntax; it’s actually a virtue to go lambda-code everything.&#8221;
Eich认为现在是程序语言发展的第二个黄金时代，应该重视语言本身的改进，不能止步不前，由于web重视兼容性，所以JS止步的太久，但不能以此为借口拒绝改进。
关于为什么要改进
跟Doug Crockford相反，Eich认为JS不能过于精简化、子集化，不能只保持de-sugar之后的几个原始特性（比如lambda），因为:
&#8220;It’s very reductionistic and it’s not for everybody.&#8221;
 &#8220;Subsetting is powerful. But to say everyone has to program in this sort of minuscule subset, that’s [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.limboy.com/wp-content/uploads/2011/04/codersatwork.jpg"><img src="http://www.limboy.com/wp-content/uploads/2011/04/codersatwork-200x300.jpg" width="200" height="300" class="alignnone size-medium wp-image-389" style="float:left;margin:0 15px 10px 0;" /></a><em>这篇是之前发在<a href="http://book.douban.com/people/Dexter_Yy/annotation/5355285/">豆瓣读书笔记</a>里的内容。其他<a href="http://www.douban.com/note/147067689/">更零碎的东西</a>就不搬运过来了，平时都发在google reader note和豆瓣日记/推荐里~</em></p>
<p>JavaScript用户的斯德哥尔摩综合症：微软不想改进，所以这语言也就这样了，用lambda代码来实现所有东西是一个优势，干嘛还要更好的语法</p>
<blockquote><p>&#8220;Oh, it only does what it does because Microsoft stopped letting it improve, so why should we want better syntax; it’s actually a virtue to go lambda-code everything.&#8221;</p></blockquote>
<p>Eich认为现在是程序语言发展的第二个黄金时代，应该重视语言本身的改进，不能止步不前，由于web重视兼容性，所以JS止步的太久，但不能以此为借口拒绝改进。</p>
<h2>关于为什么要改进</h2>
<p>跟Doug Crockford相反，Eich认为JS不能过于精简化、子集化，不能只保持de-sugar之后的几个原始特性（比如lambda），因为:<span id="more-383"></span></p>
<blockquote><p>&#8220;It’s very reductionistic and it’s not for everybody.&#8221;</p></blockquote>
<blockquote><p> &#8220;Subsetting is powerful. But to say everyone has to program in this sort of minuscule subset, that’s not usable.&#8221;</p></blockquote>
<blockquote><p>&#8220;tries to make everybody into an expert and it will not work on the large number of programmers out there who have been mistrained in these Java schools.&#8221;</p></blockquote>
<p>当初不把JS设计成一个纯粹的lambda x86语言的理由也是一样：不是每个人都想成为superhacker，程序员中也有一个金字塔。</p>
<p>lambda是JS的理论优势，但Eich认为要让JS兼具理论和实用的优势，就不能仅仅为了纯洁性而放弃好用的功能。</p>
<p>Doug等人传播了一些模式去解决JS的问题，某种程度上来说很成功，让普通开发者们在patterny level上了解到很多函数式编程的概念和惯用法，但Eich更同意Peter Norvig的观点：模式反映出程序语言本身存在某种缺陷。这些模式不是免费的午餐。</p>
<p>另一个改进的理由是，尽管程序员们可以通过写抽象库，自己解决很多问题（而且Eich非常欣赏一些JS库，认为它们令人振奋，反映了人们是何等聪明，能用非常小的工具集做出非常合理非常方便的抽象），但这种抽象能力在现有的语言中还是受到了很大限制，所以语言本身需要扩展。</p>
<h2>关于如何作改进</h2>
<p>除了Eich的blog连发的三篇文章里提到过的重大改进（比如proxy和for-in语法），这篇采访里还反映出他本来早就想引入macro，因为担心这个过程耗时很长研究性质很强，没办法吸引到微软，所以暂时搁置了，但他们一直在确保现有的和即将加入的语法糖能随时转化成宏:</p>
<blockquote><p>&#8220;we do make sure we can recast all of the sugar as macros when we have macros.&#8221;</p></blockquote>
<p>当Seibel询问对Knuth的文学化编程（literate programming）的看法时，Eich提到他对于doc comments和doc strings的兴趣，认为缺乏自动从注释里提取信息转化成可读文字和自动检查的手段，literate programming包含了整合测试和注释的含义。他们曾在ES4里做过尝试（AS3的metadata算么）：</p>
<blockquote><p>&#8220;We tried to add doc comments of some sort to ES4 with first-class metadata hooks or reflection hooks and it was just impossible to get everybody to agree.&#8221;</p></blockquote>
<p>此外Eich对静态语法分析有极大的兴趣（他的blog里也有相关的文章），他提到这是他们希望JS具备可选类型的原因之一：</p>
<blockquote><p>
&#8220;That was one of the reasons why in JavaScript we were interested in optional typing and we still are, though it’s controversial in the committee. There’s still a strong chance we’ll get some kind of hybrid type system into a future version of JavaScript.&#8221;</p></blockquote>
<p>嗯嗯其实我想说的是……以上三点（宏、文档注释、静态分析）正好都包含在我去年开发的JS预处理器的愿景之中呀~木哈哈哈哈，所见略同所见略同~</p>
<p>好罢这其实是111页的前后几页的笔记……不过都是同一个话题……</p>
<p>P.S. 学到一个新的骂人话：Java是一种“blue-collar language”（中文版翻译成“IT民工语言”） </p>
<p>再P.S. 全篇都充斥着Eich和Doug的基情口牙~~提到Doug的次数太多了~比如：</p>
<blockquote><p>Seibel: Was the ES4 proposal your chance to show the world that, “Look, I’m a really smart guy and JavaScript is a really a good language”? </p></blockquote>
<blockquote><p>Eich: No, I don’t think so. I know Doug may think that. I don’t think Doug knows me that well, but the thing is, I’m not really looking for respect, especially from the Java-heads or the trailing edge.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2011/04/23/brendan-eich-in-codersatwork/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>GrassMudMonkey: 浏览器里的草泥马程序解释器</title>
		<link>http://www.limboy.com/2010/03/21/grassmudmonkey/</link>
		<comments>http://www.limboy.com/2010/03/21/grassmudmonkey/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 04:38:05 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[kuso]]></category>
		<category><![CDATA[代码]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2010/03/21/grassmudmonkey/</guid>
		<description><![CDATA[一款具有划时代意义的产品隆重面世！来自中国民营企业土豆网的高级资深前端总工程师瀚主程序员瀚首席前端架构师德克斯特同志（Fellow Dexter the Advanced Senior Principal Front-end Engineer &#038; Chief Programmer &#038; Lead Architect）胸怀大志，以民族振兴和国家富强为己任，充分发扬自力更生自主创新的精神，在没看过龙书没读完SCIP的简陋条件下，敢打敢拼，艰苦朴素，不吃饭不喝水不晒衣服，终于研发出了可以在浏览器中运行草泥马程序的纯JavaScript实现的草泥马引擎GrassMudMonkey，这标志着中国自主知识产权的编程语言——草泥马语（GrassMudHorse Programming Language）——在核心技术上又取得了重大突破，打破了谷歌，魔斯拉等西方国家企业在浏览器内嵌脚本技术上的垄断，为三网融合瀚大中华局域网的发展创造了良好的技术条件，回首往昔，展望未来，完全基于汉字的编程方式的普及必将推动民族凝聚，促进和谐，有效抵制西方文化入侵乃至外星使徒入侵。
草泥马语是一种轻量的，简洁的，紧凑的，图灵完备的，基于堆栈的语言，与美国瀚北欧企业开发的JägerMonkey，Nitro，V8，Carakan等浏览器内嵌引擎支持的JavaScript语言相比，草泥马语仅使用“草”，“泥”，“马”三个字符来完成一切任务，其语言设计的先进性和前瞻性，不仅被全球开发社区争相学习借鉴，应用到CPU和单片机的指令设计中，甚至还已经出现了相似度高达97%的山寨项目
学习草泥马语的最快方式是阅读官方项目组发布的草泥马语言规范及其英文翻译版
GrassMudMonkey利用JavaScript来实现词法分析和运行时，完整源代码：http://github.com/dexteryy/GrassMudMonkey/blob/master/grassmudmonkey.js
效果演示 / 在线的集成开发环境（提供控制台）：
默认示例里的程序通过循环输出1到10的整数
[单独打开]

注意事项1: 由于美学智慧上的分歧，GrassMudMonkey跟官方的JAVA版本有细微区别：不支持“河蟹”。
注意事项2：仅仅针对一两段程序做了基准测试，涵盖了大部分指令，但不排除有实现不一致的地方。
注释事项3：输入接口懒得写了，全部返回默认值，whitespace网站上的一些示例程序会因此无法运行。
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2010/03/gmh.jpg' title='gmh.jpg' target="_blank"><img src='http://www.limboy.com/wp-content/uploads/2010/03/gmh.jpg' alt='gmh.jpg' style="width:240px;float:left;margin:0 10px 10px 0;" /></a>一款具有划时代意义的产品隆重面世！来自中国民营企业土豆网的高级资深前端总工程师瀚主程序员瀚首席前端架构师德克斯特同志（Fellow Dexter the Advanced Senior Principal Front-end Engineer &#038; Chief Programmer &#038; Lead Architect）胸怀大志，以民族振兴和国家富强为己任，充分发扬自力更生自主创新的精神，在没看过龙书没读完SCIP的简陋条件下，敢打敢拼，艰苦朴素，不吃饭不喝水不晒衣服，终于研发出了可以在浏览器中运行草泥马程序的<a href="http://github.com/dexteryy/GrassMudMonkey" target="_blank">纯JavaScript实现的草泥马引擎GrassMudMonkey</a>，这标志着中国自主知识产权的编程语言——<a href="http://code.google.com/p/grass-mud-horse/" target="_blank">草泥马语（GrassMudHorse Programming Language）</a>——在核心技术上又取得了重大突破，打破了谷歌，魔斯拉等西方国家企业在浏览器内嵌脚本技术上的垄断，为三网融合瀚大中华局域网的发展创造了良好的技术条件，回首往昔，展望未来，完全基于汉字的编程方式的普及必将推动民族凝聚，促进和谐，有效抵制西方文化入侵乃至<a href="http://www.tudou.com/playlist/playindex.do?lid=8172334" target="_blank">外星使徒入侵</a>。<span id="more-255"></span></p>
<p>草泥马语是一种轻量的，简洁的，紧凑的，图灵完备的，基于堆栈的语言，与美国瀚北欧企业开发的JägerMonkey，Nitro，V8，Carakan等浏览器内嵌引擎支持的JavaScript语言相比，草泥马语仅使用“草”，“泥”，“马”三个字符来完成一切任务，其语言设计的先进性和前瞻性，不仅被全球开发社区争相学习借鉴，应用到CPU和单片机的指令设计中，甚至还已经出现了<a href="http://compsoc.dur.ac.uk/whitespace" target="_blank">相似度高达97%的山寨项目</a></p>
<p>学习草泥马语的最快方式是阅读官方项目组发布的<a href="http://code.google.com/p/grass-mud-horse/wiki/A_Brife_To_GrassMudHorse_Language" target="_blank">草泥马语言规范</a>及其<a href="http://compsoc.dur.ac.uk/whitespace/tutorial.php" target="_blank">英文翻译版</a></p>
<p>GrassMudMonkey利用JavaScript来实现词法分析和运行时，完整源代码：<a href="http://github.com/dexteryy/GrassMudMonkey/blob/master/grassmudmonkey.js" target="_blank">http://github.com/dexteryy/GrassMudMonkey/blob/master/grassmudmonkey.js</a></p>
<p>效果演示 / 在线的集成开发环境（提供控制台）：</p>
<p>默认示例里的程序通过循环输出1到10的整数</p>
<p><a href="http://www.limboy.com/demo/gmm/demo.html" target="_blank">[单独打开]</a><br />
<iframe src="http://www.limboy.com/demo/gmm/demo.html" width="490" height="600" frameborder="0"></iframe></p>
<p>注意事项1: 由于美学智慧上的分歧，GrassMudMonkey跟官方的JAVA版本有细微区别：不支持“河蟹”。</p>
<p>注意事项2：仅仅针对一两段程序做了基准测试，涵盖了大部分指令，但不排除有实现不一致的地方。</p>
<p>注释事项3：输入接口懒得写了，全部返回默认值，whitespace网站上的一些示例程序会因此无法运行。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2010/03/21/grassmudmonkey/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>[内销转出口]寻找最好的JavaScript面向对象模式和封装结构</title>
		<link>http://www.limboy.com/2009/09/20/tudou-javascript-oop-and-module-guideline/</link>
		<comments>http://www.limboy.com/2009/09/20/tudou-javascript-oop-and-module-guideline/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 05:02:22 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[土豆网]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/09/20/tudou-javascript-oop-and-module-guideline/</guid>
		<description><![CDATA[好久不见，这次发的不是笔记啦，是我在公司内部的前端wiki上更新的文档……这个抛弃所有wiki语法要求用户直接手写语义化html用json配置导航的wiki排版相当漂亮，让我这样的懒人也有了码字的欲望，发起人小麦实在系功德无量……

这篇文章去年就准备写，想用循序渐进的形式推演出一个Module Pattern的最佳实践，不过想法越多，归纳总结表达出来的成本就越高，所以一直拖延……这次发的文档是一个简化版，去掉了各式各样乱七八糟的写法，只包含几个常用的，说明文字也不多主要看代码-__-b……初衷是作为给土豆前端team里新来的同事看的提纲（对了由于某人叛逃到产品设计部门，现在又空出一个名额，有兴趣的同学抓紧时间投简历，这次是魔都总部的职位，不是成都的），所以要解释一下，文档中提到的TUI是一个js库（名字是很俗，不过我上次发现某年纪一大把的人也跟我一样俗），土豆一直采用双库并行（不要看成双工并行…）的形式，在紧跟开源社区发展的同时自己掌控所有环节和基础架构，没有使用jQuery UI和那套基于DOM的插件结构，而jQuery自己几乎不提供OOP工具（这是好事），实际上自己创建这类工具非常简单快捷，相关的代码我提取了一下直接帖在末尾了，仅供参考。
另外，为了符合Nicholas Zakas在最近的国际会议上传达的精神，我修改了若干变量名跟他ppt里的例子保持一致——这件事教育我们，平时多上slideshow.net对保持先进性是多么重要。
Tudou&#8217;s JavaScript Guideline &#8212; OOP and Module
介绍土豆在面向对象和模块化设计方面的工具和实践

&#8220;Don&#8217;t Repeat Yourself.&#8221; (DRY)
&#8220;Rather than construction, programming is more like gardening.&#8221;
Quote from: Andy Hunt and Dave Thomas, The Pragmatic Programmer
			

索引

创建类，继承，混入，实例化
模块化 Module Pattern
沙盒，模块间的解耦，与外部通信
按需加载模块 On-demand Lazy Load
总结


创建类，继承，混入，实例化
我们依赖的核心工具是TUI.clone
简洁的，支持私有属性，不需要prototype的写法：
JS是基于原型而不是基于类的面向对象语言，JS是“无类型”的，类是仿造出来的概念，实质只有对象。
new只是用来复制对象，构造函数只是用来返回对象, 两者对JS的OOP来说并不是必须的。
var dog = function(options){
&#160; &#160; var&#160;privateAttr = 1; //私有属性
&#160; &#160; var&#160;private_method = function(){}; //私有方法
&#160; &#160; return&#160;{
&#160; &#160; &#160; &#160; option: options, [...]]]></description>
			<content:encoded><![CDATA[<p>好久不见，这次发的不是笔记啦，是我在公司内部的前端wiki上更新的文档……这个抛弃所有wiki语法要求用户直接手写语义化html用json配置导航的wiki排版相当漂亮，让我这样的懒人也有了码字的欲望，发起人小麦实在系功德无量……</p>
<p><a href='http://www.limboy.com/wp-content/uploads/2009/09/picture-2.png' title='picture-2.png' target="_blank"><img src='http://www.limboy.com/wp-content/uploads/2009/09/picture-2.png' alt='picture-2.png' style="width:200px;margin:5px;" /></a><a href='http://www.limboy.com/wp-content/uploads/2009/09/picture-3.png'  target="_blank"><img src='http://www.limboy.com/wp-content/uploads/2009/09/picture-3.png' alt='picture-3.png'  style="width:200px;margin:5px;" /></a></p>
<p>这篇文章去年就准备写，想用循序渐进的形式推演出一个<a href="http://www.yuiblog.com/blog/2007/06/12/module-pattern/" target="_blank">Module Pattern</a>的最佳实践，不过想法越多，归纳总结表达出来的成本就越高，所以一直拖延……这次发的文档是一个简化版，去掉了各式各样乱七八糟的写法，只包含几个常用的，说明文字也不多主要看代码-__-b……初衷是作为给土豆前端team里新来的同事看的提纲（对了由于某人叛逃到产品设计部门，现在又空出一个名额，有兴趣的同学抓紧时间<a href="http://www.mikkolee.com/256" target="_blank">投简历</a>，这次是魔都总部的职位，不是成都的），所以要解释一下<span id="more-240"></span>，文档中提到的<var>TUI</var>是一个js库（名字是很俗，不过我上次发现某年纪一大把的人也跟我<a href="http://blog.digg.com/?p=621" target="_blank">一样俗</a>），土豆一直采用双库并行（不要看成双工并行…）的形式，在紧跟开源社区发展的同时自己掌控所有环节和基础架构，没有使用jQuery UI和那套基于DOM的插件结构，而jQuery自己几乎不提供OOP工具（这是好事），实际上自己创建这类工具非常简单快捷，相关的代码我提取了一下直接帖在末尾了，仅供参考。</p>
<p>另外，为了符合Nicholas Zakas在最近的<a href="http://www.yuiblog.com/blog/2009/09/17/video-bayjax-sept-09/" target="_blank">国际会议</a>上传达的精神，我修改了若干变量名跟他<a href="http://www.slideshare.net/nzakas/scalable-javascript-application-architecture" target="_blank">ppt</a>里的例子保持一致——这件事教育我们，平时多上slideshow.net对保持先进性是多么重要。</p>
<h2>Tudou&#8217;s JavaScript Guideline &#8212; OOP and Module</h2>
<p><em>介绍土豆在面向对象和模块化设计方面的工具和实践</em></p>
<blockquote>
<p>&#8220;Don&#8217;t Repeat Yourself.&#8221; (DRY)</p>
<p>&#8220;Rather than construction, programming is more like gardening.&#8221;</p>
<p><cite>Quote from: Andy Hunt and Dave Thomas, The Pragmatic Programmer</cite>
			</p></blockquote>
<div class="section">
<h2>索引</h2>
<ol>
<li><a href="#sec-1">创建类，继承，混入，实例化</a></li>
<li><a href="#sec-2">模块化 Module Pattern</a></li>
<li><a href="#sec-3">沙盒，模块间的解耦，与外部通信</a></li>
<li><a href="#sec-4">按需加载模块 On-demand Lazy Load</a></li>
<li><a href="#sec-5">总结</a></li>
</ol></div>
<div class="section" id="sec-1">
<h2>创建类，继承，混入，实例化</h2>
<p>我们依赖的核心工具是<var>TUI.clone</var></p>
<h3>简洁的，支持私有属性，不需要prototype的写法：</h3>
<p>JS是基于原型而不是基于类的面向对象语言，JS是“无类型”的，类是仿造出来的概念，实质只有对象。<br />
<var>new</var>只是用来复制对象，构造函数只是用来返回对象, 两者对JS的OOP来说并不是必须的。</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">dog</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">privateAttr</span><span style="color: Gray;"> = </span><span style="color: Maroon;">1</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//私有属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">private_method</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(){}</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//私有方法</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">option</span><span style="color: Gray;">: </span><span style="color: Blue;">options</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//实例属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">method1</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">xiaobai</span><span style="color: Gray;"> = </span><span style="color: Blue;">dog</span><span style="color: Olive;">({})</span><span style="color: Gray;">;</span></li></ol></div>
<ul>
<li>对私有属性/方法的支持比较好</li>
<li>最适合单例模式(Singleton)</li>
<li>延迟单例的初始化，提高页面初始化的速度</li>
<li>缺点：对继承的支持不佳</li>
<li>缺点：在需要频繁创建大量对象，而方法非常多的场合，浪费资源（因为每个实例的方法指向的都是不同的函数对象，每次实例化都要重新生成所有函数）</li>
</ul>
<p>在第2个缺点的场合，传统的prototype写法效率更高，支持继承，但是代码分散，不易读，TUI.clone提供了更好的写法——</p>
<h3>传统的、支持继承的、仿Ruby风格的Class写法：</h3>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">//创建新类</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Dog</span><span style="color: Gray;"> = </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">newClass</span><span style="color: Olive;">({</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">initialize</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span><span style="color: Gray;">&nbsp;</span><span style="color: #ffa500;">//构造函数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">option</span><span style="color: Gray;"> = </span><span style="color: Blue;">options</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">//实例化</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">xiaobai</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;"> </span><span style="color: Blue;">Dog</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">//继承</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Cat</span><span style="color: Gray;"> = </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">newClass</span><span style="color: Olive;">(</span><span style="color: Blue;">dog</span><span style="color: Gray;">, </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//只允许单继承</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">mixin</span><span style="color: Gray;">: </span><span style="color: Olive;">[</span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">event</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//混入其他方法</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">initialize</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">superClass</span><span style="color: Gray;">.</span><span style="color: Blue;">call</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//调用父类构造函数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<ul>
<li>风格类似<var>mootools</var>的<var>new Class</var></li>
<li><var>TUI.newClass</var>只是<var>TUI.clone</var>的封装</li>
<li><var>mixin</var>相当于在构造函数里<var>$.extend(this.prototype, TUI.event)</var></li>
<li>实际上应该少用继承，多用mixin和组合模式，后者更符合JS的特点</li>
<li>缺点：封装效果不好，不支持私有属性和方法</li>
</ul>
<p><var>TUI.clone</var>既可以复制构造函数的<var>prototype</var>，也可以直接复制对象（跟jQuery.extend不同，依靠原型继承），所以利用它直接生成实例。</p>
<p>这样可以在不引入<var>prototype</var>和语法糖的情况下把第一种方法改造的同样高效——</p>
<h3>对象克隆工厂的写法：</h3>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">dog</span><span style="color: Gray;"> = </span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">jQuery</span><span style="color: Gray;">, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">){</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//传入需要访问的全局命名空间</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">xxx</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//不作为状态的私有属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">private_method</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//私有方法</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">alert</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">option</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">PublicObj</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//相当于prototype对象</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">method1</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">private_method</span><span style="color: Gray;">.</span><span style="color: Blue;">call</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//访问私有方法, 共享状态</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//对象工厂</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> = </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">clone</span><span style="color: Olive;">(</span><span style="color: Blue;">PublicObj</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//克隆</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">obj</span><span style="color: Gray;">.</span><span style="color: Blue;">aption</span><span style="color: Gray;"> = </span><span style="color: Blue;">options</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//构造函数中的常规任务</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; $.</span><span style="color: Blue;">extend</span><span style="color: Olive;">(</span><span style="color: Blue;">obj</span><span style="color: Gray;">, </span><span style="color: Blue;">cat</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//mixin其他对象的方法</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})(</span><span style="color: Blue;">jQuery</span><span style="color: Gray;">, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">xiaobai</span><span style="color: Gray;"> = </span><span style="color: Blue;">dog</span><span style="color: Olive;">({})</span><span style="color: Gray;">;</span></li></ol></div>
<ul>
<li>效率高，封装好，耦合少易于修改和扩展</li>
<li>缺点：私有属性不能作为实例状态</li>
</ul>
<p>把以上第一种方法和第三种方法结合互补，为module模式——</p>
</p></div>
<div class="section" id="sec-2">
<h2>模块化 Module Pattern</h2>
<p>核心工具是<var>TUI.module</var></p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">widget</span><span style="color: Gray;">.</span><span style="color: Blue;">dog</span><span style="color: Gray;"> = </span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Gray;">$, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">){</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//除了库的命名空间，尽量不访问全局变量</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">//所有模块代码都封闭在这个区域内</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">xxx</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//不作为状态的私有属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">private_method</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//私有方法</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">alert</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">option</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">privateObj</span><span style="color: Gray;"> = </span><span style="color: Olive;">{}</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//可作为状态的私有属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">privateAttr</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">name</span><span style="color: Gray;">, </span><span style="color: Blue;">value</span><span style="color: Olive;">){</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//读写私有属性的方法，只能在内部使用</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">p</span><span style="color: Gray;"> = </span><span style="color: Green;">private</span><span style="color: Olive;">[</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">objectId</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;">!</span><span style="color: Blue;">p</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">p</span><span style="color: Gray;"> = </span><span style="color: Green;">private</span><span style="color: Olive;">[</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">objectId</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: Olive;">{}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">value</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">p</span><span style="color: Olive;">[</span><span style="color: Blue;">name</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: Blue;">value</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">p</span><span style="color: Olive;">[</span><span style="color: Blue;">name</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">dog</span><span style="color: Gray;"> = </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">newClass</span><span style="color: Olive;">(</span><span style="color: Blue;">parentClass</span><span style="color: Gray;">, </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">mixin</span><span style="color: Gray;">: </span><span style="color: Olive;">[</span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">event</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//混入其他方法</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">initialize</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">superClass</span><span style="color: Gray;">.</span><span style="color: Blue;">call</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//访问父类构造函数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">public_method</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = </span><span style="color: Blue;">a</span><span style="color: Gray;"> + </span><span style="color: Blue;">privateAttr</span><span style="color: Gray;">.</span><span style="color: Blue;">call</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">c</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//访问私有属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">private_method</span><span style="color: Gray;">.</span><span style="color: Blue;">call</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//访问私有方法</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;&nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">//工厂方法，给别人使用的接口</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;"> </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">dog</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">//实例加上唯一的ID，类似Ruby，注意只用+new Date()不能避免重复</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">obj</span><span style="color: Gray;">.</span><span style="color: Blue;">objectId</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">tui_object</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> + </span><span style="color: Olive;">(</span><span style="color: Gray;"> +</span><span style="color: Green;">new</span><span style="color: Gray;">&nbsp;</span><span style="color: Teal;">Date</span><span style="color: Olive;">()</span><span style="color: Gray;">*</span><span style="color: Maroon;">10000</span><span style="color: Gray;"> + </span><span style="color: Teal;">Math</span><span style="color: Gray;">.</span><span style="color: Blue;">random</span><span style="color: Olive;">(</span><span style="color: Maroon;">1</span><span style="color: Olive;">)</span><span style="color: Gray;">*</span><span style="color: Maroon;">10000</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})(</span><span style="color: Blue;">jQuery</span><span style="color: Gray;">, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li></ol></div>
<p>为了便于理解，以上代码是集中在一起的简单实现，进一步封装之后，有些步骤可以省略：</p>
<ul>
<li><var>objectId</var>的初始化已经由<var>TUI.clone</var>实现</li>
<li><var>privateAttr</var>方法和私有属性map由<var>TUI.newModule</var>实现</li>
<li><var>TUI.newModule</var>是<var>TUI.namespace</var>和<var>TUI.module.create</var>的封装</li>
</ul>
<h3>基于 TUI.clone 和 TUI.newModule 的写法</h3>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">newModule</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">TUI.widget.dog</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">sandbox</span><span style="color: Gray;">, $, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">dog</span><span style="color: Gray;"> = </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">newClass</span><span style="color: Olive;">(</span><span style="color: Blue;">parentClass</span><span style="color: Gray;">, </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">mixin</span><span style="color: Gray;">: </span><span style="color: Olive;">[</span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">event</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">sandbox</span><span style="color: Gray;">: </span><span style="color: Blue;">sandbox</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//有sandbox属性传入时，attr属性会被转化为外部无法访问的私有属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">attr</span><span style="color: Gray;">: </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span><span style="color: #ffa500;">//初始化私有属性的默认值</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">a</span><span style="color: Gray;">: </span><span style="color: Maroon;">1</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">b</span><span style="color: Gray;">: </span><span style="color: Maroon;">2</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">initialize</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">superClass</span><span style="color: Gray;">.</span><span style="color: Blue;">call</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//访问父类构造函数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">public_method</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">attr</span><span style="color: Olive;">(</span><span style="color: Blue;">sandbox</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">a</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;"> + </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">attr</span><span style="color: Olive;">(</span><span style="color: Blue;">sandbox</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">c</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//访问私有属性，通过sandbox参数来验证身份</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;&nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;"> </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">dog</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Blue;">jQuery</span><span style="color: Gray;">, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">xiaobai</span><span style="color: Gray;"> = </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">widget</span><span style="color: Gray;">.</span><span style="color: Blue;">dog</span><span style="color: Olive;">({})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">console</span><span style="color: Gray;">.</span><span style="color: Blue;">log</span><span style="color: Olive;">(</span><span style="color: Blue;">xiaobai</span><span style="color: Gray;">.</span><span style="color: Blue;">sandbox</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//undefined</span></li>
<li><span style="color: Blue;">console</span><span style="color: Gray;">.</span><span style="color: Blue;">log</span><span style="color: Olive;">(</span><span style="color: Blue;">xiaobai</span><span style="color: Gray;">.</span><span style="color: Blue;">attr</span><span style="color: Olive;">)</span><span style="color: Gray;">;&nbsp; &nbsp; </span><span style="color: #ffa500;">//undefined</span></li></ol></div>
<p>这里的<var>sandbox</var>其实还可以做很多事——</p>
</p></div>
<div class="section" id="sec-3">
<h2>沙盒，模块间的解耦，与外部通信</h2>
<p><var>TUI.module.create</var>方法其实来自<var>TUI.moduleClass</var>的实例，其他独立应用同样可以继承<var>TUI.moduleClass</var>，构造自己的沙盒对象</var></p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">Douwan</span><span style="color: Gray;"> = </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">newClass</span><span style="color: Olive;">(</span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">moduleClass</span><span style="color: Gray;">, </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">notify</span><span style="color: Gray;">: </span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">clone</span><span style="color: Olive;">(</span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">event</span><span style="color: Olive;">)</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//事件在这里可以理解为通信器</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">initialize</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">options</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">me</span><span style="color: Gray;"> = </span><span style="color: Green;">this</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">_sandbox</span><span style="color: Gray;">.</span><span style="color: Blue;">notify</span><span style="color: Gray;"> = </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">notify</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//把通信器指向自己，避免跟全局的事件命名冲突</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">//给沙盒增加ajax方法，让module内的代码通过沙盒来通信，屏蔽url路径和响应格式之类的细节</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">url</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">http://www.tudou.com/path/service.action</span><span style="color: #8b0000;">&quot;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">_sandbox</span><span style="color: Gray;">.</span><span style="color: Blue;">getJSON</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">param</span><span style="color: Gray;">, </span><span style="color: Blue;">fn</span><span style="color: Olive;">){</span><span style="color: Gray;">&nbsp;</span><span style="color: #ffa500;">//模块只需要传url参数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">me</span><span style="color: Gray;">.</span><span style="color: Blue;">getJSON</span><span style="color: Olive;">(</span><span style="color: Blue;">url</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">text</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">jsondata</span><span style="color: Gray;"> = </span><span style="color: Blue;">me</span><span style="color: Gray;">.</span><span style="color: Blue;">toJSON</span><span style="color: Olive;">(</span><span style="color: Blue;">text</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">fn</span><span style="color: Olive;">(</span><span style="color: Blue;">jsondata</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//无论返回格式是什么，都传json给模块</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">toJSON</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">getJSON</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){}</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>让应用的不同模块之间解耦，避免在模块内部直接使用外部的命名（除了库的api）</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">douwanObj</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;"> </span><span style="color: Blue;">Douwan</span><span style="color: Olive;">({})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">module1</span><span style="color: Gray;"> = </span><span style="color: Blue;">douwanObj</span><span style="color: Gray;">.</span><span style="color: Blue;">module</span><span style="color: Gray;">.</span><span style="color: Blue;">create</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">sandbox</span><span style="color: Gray;">, $, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">sandbox</span><span style="color: Gray;">.</span><span style="color: Blue;">getJSON</span><span style="color: Olive;">({</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">iid</span><span style="color: Gray;">: </span><span style="color: Maroon;">10000</span><span style="color: Gray;"> </span><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">//通过通信器调用module2.update</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">sondbox</span><span style="color: Gray;">.</span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">fire</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">module2-update</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Blue;">json</span><span style="color: Gray;">.</span><span style="color: Blue;">date</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Blue;">JQuery</span><span style="color: Gray;">, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">module2</span><span style="color: Gray;"> = </span><span style="color: Blue;">douwanObj</span><span style="color: Gray;">.</span><span style="color: Blue;">module</span><span style="color: Gray;">.</span><span style="color: Blue;">create</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">sandbox</span><span style="color: Gray;">, $, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">update</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">//注册一个update消息的接收器</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">sondbox</span><span style="color: Gray;">.</span><span style="color: Blue;">notify</span><span style="color: Gray;">.</span><span style="color: Blue;">bind</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">module2-update</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">date</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">obj</span><span style="color: Gray;">.</span><span style="color: Blue;">update</span><span style="color: Olive;">(</span><span style="color: Blue;">date</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Olive;">[</span><span style="color: Blue;">JQuery</span><span style="color: Gray;">, </span><span style="color: Blue;">TUI</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li></ol></div>
<p>页面初始化时并不一定需要渲染或操作所有模块，因此有些模块的代码可以放在外部文件里，需要的时候再注入到页面里，类似<var>Python</var>的<var>import</var></p>
</p></div>
<div class="section" id="sec-4">
<h2>按需加载模块 On-demand Lazy Load</h2>
<p>自动管理各个模块之间的依赖关系，根据代码内容加载不同的文件，这样做的成本太高，适合大型企业应用，我们的设计原则是“恰到好处”，所以通过文件名来管理模块</p>
<h3>注册模块</h3>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">module</span><span style="color: Gray;">.</span><span style="color: Blue;">join</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">http://js.tudouui.com/js/fn/saleloader_10.js</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: Blue;">domain</span><span style="color: Gray;">: </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">http://uidev.tudou.com</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">version</span><span style="color: Gray;">: </span><span style="color: Maroon;">0</span><span style="color: Gray;"> </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<ul>
<li>配置从url里获取，第二个配置参数是可选的，优先级更高，用于调试（指向开发环境）</li>
<li>域名其实可以省略，js文件的域名通过<var>TUI.domain</var>和autodomain.js脚本来自动配置</li>
<li>版本号很重要，支持a_10.js/a.v10.js/a_v10.js等写法</li>
</ul>
<h3>使用模块</h3>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">module</span><span style="color: Gray;">.</span><span style="color: Blue;">use</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">/fn/saleloader</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">adExtension</span><span style="color: Gray;">.</span><span style="color: Blue;">load</span><span style="color: Olive;">()</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//这个是saleloader.js内的方法，必须等js加载完后执行</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">//这个区域是执行saleloader.js内代码的安全空间</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<ul>
<li>类似YUI3的<var>Y().use</var>，省去了版本冲突之类无用的特性</li>
<li>第一次use时会向页面里加载对应的script</li>
<li>函数区域内的代码是异步执行的，会等到saleloader.js加载完后依次执行，如果已经加载过了，直接执行，类似<var>jQuery.ready</var></li>
</ul></div>
<div class="section" id="sec-5">
<h2>总结</h2>
<ul>
<li>以上方法虽然有递进关系，但并不是要表示最后面的才是最好的方法</li>
<li>最好的方法不是唯一的，要根据场合选择最适合的方法，以上方法都有适用场合</li>
<li>本文档涉及到的API：<var>TUI.clone</var>, <var>TUI.newClass</var>, <var>TUI.moduleClass</var>, <var>TUI.module.create</var>, <var>TUI.newModule</var>, <var>TUI.module.join</var>, <var>TUI.module.use</var>, <var>TUI.event</var></li>
</ul></div>
<p>=============开始帖源码的分割线=============</p>
<h3>TUI.clone</h3>
<pre><code>
	/**
	 * @public 继承一个类或复制一个对象
	 * @note
	 * @param {object|function} oldone是需要继承的构造函数或需要复制的对象
	 * @param {object|function} ex为函数时，是子类的构造函数，或者用来加工新对象
	 * 						ex为对象时，为子类的方法, 其中initialize方法为构造函数, mixin为混入的超类
	 * @return {object|function}
	 */
	clone: function(oldone, ex){
		var newobj,
			isClass = !oldone || $.isFunction(oldone), //继承操作
			constructorFn = ex &#038;&#038; !$.isFunction(ex) &#038;&#038; ex.initialize || ex; //子类构造函数
		if (!isClass) {
			newobj = function(){
				if(constructorFn)
					constructorFn.apply(this, arguments);
			};
			newobj.prototype = oldone;
			return new newobj();
		} else {
			 //为module内部定义的类提供相关方法
			var c = { _sandbox: ex.sandbox, _default: ex.attr };
			newobj = function(){ //构造函数
				if (this.constructor === newobj) { // 如果this指向子类实例，已经执行过以下的初始化代码
					this.objectId = "TUI-object-" + ++obj_uuid; //实例的唯一ID
					var p = c;
					if (p._sandbox &#038;&#038; p._default)
						this.attr(p._sandbox, p._default); //初始化私有属性的默认值
				}
				if(constructorFn) //执行构造函数的自定义部分
					constructorFn.apply(this, arguments);
			};
			// 原型继承, 子类构造函数里需要显示调用父类构造函数
			var newproto = oldone ? this.clone(oldone.prototype) : {};
			// 混入其他超类方法
			if (ex.mixin)
				this.mix.apply(this, ([newproto]).concat(ex.mixin));
			// 加入子类方法, 覆盖混入和继承
			this.mix(newproto, ex, {
				constructor: newobj, // 恢复
				superClass: oldone || Object //在子类的构造函数中可以用this.superClass访问父类
			});
			delete newproto.initialize;
			if (c._sandbox) {
				delete newproto.sandbox; //沙盒一定要删除，不能暴露出去
				newproto.attr = function(sandbox, attrname, value){ //通过sandbox参数杜绝来自外部的访问
					return sandbox.attr.call(this, attrname, value);
				};
			}
			newobj.prototype = newproto;
			return newobj;
		}
	}

</code></pre>
<h3>TUI.moduleClass</h3>
<pre><code>
/**
 * 存放实例的私有状态
 * @private
 */
var privateAttr = {};
/**
 * module的抽象类
 * @note 可以继承到其他应用上, 构造独有的sandbox
 */
TUI.moduleClass = TUI.newClass({
	initialize: function(){
		this.notify = new TUI.eventClass();
		this._sandbox.notify = this.notify; //被继承的时候，notify可以另外指向到别处
	},
	_sandbox: {
		attr: function(name, value){ //this指向调用它的实例
			if (typeof name === "object") {
				privateAttr[this.objectId] = TUI.clone(name); //初始化私有变量的默认值
				return true;
			}
			var p = privateAttr[this.objectId];
			if (!p) //尽量在module里初始化
				p = privateAttr[this.objectId] = {};
			if (value)
				p[name] = value;
			return p[name];
		}
	},
	/**
	 * 创建一个模块，提供封闭的代码作用域和沙盒
	 * @public
	 * @param {function}
	 * @param {object} args参数
	 */
	create: function(wrap, op){
		var sandbox = TUI.clone(this._sandbox),
			args = op.args || [],
			ns = {};
		args.unshift(sandbox);
		return wrap.apply(ns, args) || ns;
	}
});

$.extend(TUI.module, new TUI.moduleClass());
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/09/20/tudou-javascript-oop-and-module-guideline/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>HTML5, CSS3, ES5&#8230;新的web标准和浏览器支持一览</title>
		<link>http://www.limboy.com/2009/06/29/html5-css3-es5-support/</link>
		<comments>http://www.limboy.com/2009/06/29/html5-css3-es5-support/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 00:40:26 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[web服务/应用]]></category>
		<category><![CDATA[代码]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/06/29/html5-css3-es5-support/</guid>
		<description><![CDATA[好罢这篇本来是我私下做的笔记，我特别喜欢在Evernote上做备忘的笔记，虽然上次看到漏屋老师的文章里说我现在的年龄才刚刚进入记忆力的巅峰期……但是我的自信心仍然屡受打击！比如跟别人讨论The Dark Knight里小丑在医院对检察官说了什么让他变成双面人，我一句对白都想不起来，还有big bang theory s2里penny玩age of conan时的人物名字是&#8221;Queen Penelope&#8221;，我看的时候印象很深，一个月后就连奥德赛都想不起来了。留份笔记总觉得心里踏实些……啊又跑题了
本文整理了一些最重要（或者说人气比较高罢）的新标准，虽然它们多数还只是w3c的草案，离Recommendation级别还早，却已经成为新一轮浏览器大战中备受追捧的明星，开发者社区里也涌现出大量相关的demo和API封装，有些已经进入生产环境（比如google在iphone上实现的gmail离线应用），其实我觉得如今的web领域里，从厂商私有技术转换成委员会标准再转换成通用技术产生杀手级应用的周期已经显著的加速了，是因为现在web application的需求太高了么…… UPDATE：刚才在solidot发软文的时候我突然想明白怎么表述这个问题：其实现在很多浏览器厂商同时也是基于浏览器的应用开发者和web标准的制定者，就好像修筑舞台的工程师同时也是舞台上的演员和舞蹈动作的导演一样，所以google, mozilla, apple们都在不遗余力的实现那些有利于开发web应用的技术标准，即时它们还是W3C Working Draft，相比之下IE team就比较缺乏动力，果然计划经济缺乏活力亚XD……
由于是源自笔记，对每个条目我只会列出称呼和语法特征，暂时没时间写详细的解释和可执行的示例，但是会给出相关的文档地址，除了列出已经支持该特性的浏览器，也会为不支持的浏览器提供替代/过渡的实现。
===================废话结束的分割线=======================
CSS3 Media queries
对整个外链css文件和部分css代码使用的媒体类型侦测，人气高的原因显然是因为移动设备……
&#60;link media=“all and (orientation:portrait)” src=&#34;screen.css&#34; type=&#34;text/css&#34;&#62;
@media all and (min-color: 4) { ... }
w3c标准：http://www.w3.org/TR/css3-mediaqueries/
MDC文档：https://developer.mozilla.org/En/CSS/Media_queries
Opera文档：http://www.opera.com/docs/specs/css/
支持：Firefox 3.5+, Safari 3+, Opera 7+

CSS3 2D Transforms
css变形，有人用这个实现伪3d效果以及旋转效果的jquery插件
-moz-transform: rotate(-45deg) skew(15deg, 15deg);
sprite.style['-webkit-transform'] = 'rotate(' + v + 'rad)';
w3c标准：http://www.w3.org/TR/css3-2d-transforms/
MDC文档：https://developer.mozilla.org/En/CSS/CSS_transform_functions
webkit博客的介绍: http://webkit.org/blog/130/css-transforms/
支持：Firefox 3.5+, Safari 3.1+
替代/过渡：IE5.5+ Matrix Filter http://msdn.microsoft.com/en-us/library/ms533014(VS.85).aspx

CSS3 Transitions and [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2009/06/29/html5-css3-es5-support/bwjpg/' rel='attachment wp-att-239' title='bw.jpg'><img src='http://www.limboy.com/wp-content/uploads/2009/06/bw.jpg' alt='bw.jpg' style="float:left;border:0;margin:0 10px 0 0;" /></a>好罢这篇本来是我私下做的笔记，我特别喜欢在<a target="_blank"  href="http://evernote.com/">Evernote</a>上做备忘的笔记，虽然上次看到<a target="_blank"  href="http://cache.tianya.cn/publicforum/content/english/1/121795.shtml">漏屋老师的文章</a>里说我现在的年龄才刚刚进入记忆力的巅峰期……但是我的自信心仍然屡受打击！比如跟别人讨论The Dark Knight里小丑在医院对检察官说了什么让他变成双面人，我一句对白都想不起来，还有big bang theory s2里penny玩age of conan时的人物名字是&#8221;Queen Penelope&#8221;，我看的时候印象很深，一个月后就连奥德赛都想不起来了。留份笔记总觉得心里踏实些……啊又跑题了</p>
<p>本文整理了一些最重要（或者说人气比较高罢）的新标准，虽然它们多数还只是w3c的草案，离Recommendation级别还早，却已经成为新一轮浏览器大战中备受追捧的明星，开发者社区里也涌现出大量相关的demo和API封装，有些已经进入生产环境（比如google在iphone上实现的<a target="_blank"  href="http://www.wired.com/epicenter/2009/02/google-turns-to/">gmail离线应用</a>），其实我觉得如今的web领域里，从厂商私有技术转换成委员会标准再转换成通用技术产生杀手级应用的周期已经显著的加速了<span id="more-238"></span>，是因为现在web application的需求太高了么…… <strong>UPDATE：</strong>刚才在solidot发软文的时候我突然想明白怎么表述这个问题：其实现在很多浏览器厂商同时也是基于浏览器的应用开发者和web标准的制定者，就好像修筑舞台的工程师同时也是舞台上的演员和舞蹈动作的导演一样，所以google, mozilla, apple们都在不遗余力的实现那些有利于开发web应用的技术标准，即时它们还是W3C Working Draft，相比之下IE team就比较缺乏动力，果然计划经济缺乏活力亚XD……</p>
<p>由于是源自笔记，对每个条目我只会列出称呼和语法特征，暂时没时间写详细的解释和可执行的示例，但是会给出相关的文档地址，除了列出已经支持该特性的浏览器，也会为不支持的浏览器提供替代/过渡的实现。</p>
<p>===================废话结束的分割线=======================</p>
<h3>CSS3 Media queries</h3>
<p>对整个外链css文件和部分css代码使用的媒体类型侦测，人气高的原因显然是因为移动设备……</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">link</span><span style="color: Gray;"> </span><span style="color: #00008b;">media</span><span style="color: Gray;">=“</span><span style="color: #00008b;">all</span><span style="color: Gray;"> </span><span style="color: #00008b;">and</span><span style="color: Gray;"> (</span><span style="color: #00008b;">orientation:portrait</span><span style="color: Gray;">)” </span><span style="color: #00008b;">src</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">screen.css</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">type</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">text/css</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span></li></ol></div>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #00008b;">@media</span><span style="color: Gray;"> </span><span style="color: Blue;">all</span><span style="color: Gray;"> </span><span style="color: Blue;">and</span><span style="color: Gray;"> (min-color: 4) </span><span style="color: Olive;">{</span><span style="color: Gray;"> ... </span><span style="color: Olive;">}</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/css3-mediaqueries/">http://www.w3.org/TR/css3-mediaqueries/</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/CSS/Media_queries">https://developer.mozilla.org/En/CSS/Media_queries</a><br />
Opera文档：<a target="_blank"  href="http://www.opera.com/docs/specs/css/">http://www.opera.com/docs/specs/css/</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, Safari 3+, Opera 7+</strong><br />
<br/></p>
<h3>CSS3 2D Transforms</h3>
<p>css变形，有人用这个实现<a target="_blank"  href="http://ajaxian.com/archives/fun-with-3d-css-and-video">伪3d效果</a>以及<a target="_blank"  href="http://www.zachstronaut.com/projects/rotate3di/">旋转效果的jquery插件</a></p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Gray;">-moz-transform: </span><span style="color: Blue;">rotate</span><span style="color: Gray;">(-45</span><span style="color: Blue;">deg</span><span style="color: Gray;">) </span><span style="color: Blue;">skew</span><span style="color: Gray;">(15</span><span style="color: Blue;">deg</span><span style="color: Gray;">, 15</span><span style="color: Blue;">deg</span><span style="color: Gray;">);</span></li></ol></div>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">sprite</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Olive;">[</span><span style="color: #8b0000;">'</span><span style="color: Red;">-webkit-transform</span><span style="color: #8b0000;">'</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">'</span><span style="color: Red;">rotate(</span><span style="color: #8b0000;">'</span><span style="color: Gray;"> + </span><span style="color: Blue;">v</span><span style="color: Gray;"> + </span><span style="color: #8b0000;">'</span><span style="color: Red;">rad)</span><span style="color: #8b0000;">'</span><span style="color: Gray;">;</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/css3-2d-transforms/">http://www.w3.org/TR/css3-2d-transforms/</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/CSS/CSS_transform_functions">https://developer.mozilla.org/En/CSS/CSS_transform_functions</a><br />
webkit博客的介绍: <a target="_blank"  href="http://webkit.org/blog/130/css-transforms/">http://webkit.org/blog/130/css-transforms/</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, Safari 3.1+</strong><br />
<strong style="color:#ff6600;">替代/过渡：IE5.5+ Matrix Filter <a target="_blank"  href="http://msdn.microsoft.com/en-us/library/ms533014(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms533014(VS.85).aspx</a></strong><br />
<br/></p>
<h3>CSS3 Transitions and CSS Animations</h3>
<p>备受期待的css动画，webkit团队提出的草案，transition实现简单的属性渐变，animation定义更复杂的动画效果</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Gray;">transition-property: </span><span style="color: Blue;">width</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">transition-duration: 1</span><span style="color: Blue;">s</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">animation-name: '</span><span style="color: Blue;">diagonal-slide</span><span style="color: Gray;">';</span></li>
<li><span style="color: Gray;">animation-duration: 5</span><span style="color: Blue;">s</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">animation-iteration-count: 10;</span></li>
<li><span style="color: #00008b;">@keyframes</span><span style="color: Gray;"> '</span><span style="color: Blue;">diagonal-slide</span><span style="color: Gray;">' </span><span style="color: Olive;">{}</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/css3-transitions/">http://www.w3.org/TR/css3-transitions/</a><br />
w3c标准：<a target="_blank"  href="http://www.w3.org/TR/css3-animations/">http://www.w3.org/TR/css3-animations/</a><br />
webkit博客的介绍：<a target="_blank"  href="http://webkit.org/blog/138/css-animation/">http://webkit.org/blog/138/css-animation/</a><br />
约翰同学的介绍：<a target="_blank"  href="http://ejohn.org/blog/css-animations-and-javascript/">http://ejohn.org/blog/css-animations-and-javascript/</a></p>
<p><strong style="color:#ff6600;">支持：Safari 3.1+</strong><br />
<br/></p>
<h3>CSS3 Downloadable fonts</h3>
<p>能在网页里嵌入任意字体是设计师的梦想……不过这里支持的也仅限truetype和opentype</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #00008b;">@font</span><span style="color: Gray;">-</span><span style="color: Blue;">face</span><span style="color: Gray;"> </span><span style="color: Olive;">{}</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/css3-fonts/#font-resources">http://www.w3.org/TR/css3-fonts/#font-resources</a><br />
MSDN文档：<a target="_blank"  href="http://msdn.microsoft.com/en-us/library/ms530303(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms530303(VS.85).aspx</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/en/CSS/@font-face">https://developer.mozilla.org/en/CSS/@font-face</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, Safari 3.1+, Opera 10.0+, IE4.0+</strong><br />
<br/></p>
<h3>附赠：其他CSS3 property的兼容性</h3>
<p>ppk同学维护的文档: <a target="_blank"  href="http://www.quirksmode.org/css/contents.html">http://www.quirksmode.org/css/contents.html</a><br />
css3.info维护的文档：<a target="_blank"  href="http://www.css3.info/modules/selector-compat/">http://www.css3.info/modules/selector-compat/</a><br />
一个测试页面：<a target="_blank"  href="http://westciv.com/iphonetests/">http://westciv.com/iphonetests/</a><br />
<br/></p>
<h3>HTML5 DOM Storage</h3>
<p>简洁的持久存储，键值对的形式</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">window.localStorage</span></li>
<li><span style="color: Blue;">window.sessionStorage</span><span style="color: Gray;"> //可跨域，标签页关掉就清空</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/webstorage/">http://www.w3.org/TR/webstorage/</a><br />
ppk同学维护的兼容性列表：<a target="_blank"  href="http://www.quirksmode.org/dom/html5.html#localstorage">http://www.quirksmode.org/dom/html5.html#localstorage</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/en/DOM/Storage">https://developer.mozilla.org/en/DOM/Storage</a><br />
MSDN文档：<a target="_blank"  href="http://msdn.microsoft.com/en-us/library/cc197062(VS.85).aspx">http://msdn.microsoft.com/en-us/library/cc197062(VS.85).aspx</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, Safari 4.0+, IE 8.0+</strong><br />
<br/></p>
<h3>HTML5 Offline Application Cache</h3>
<p>用一个manifest文件缓存静态资源（图片,css, js之类）在离线状态下使用，不是结构化数据</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">html</span><span style="color: Gray;"> </span><span style="color: #00008b;">manifest</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">foo.manifest</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span></li></ol></div>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">CACHE MANIFEST</li>
<li>index.html</li>
<li>style/default.css</li>
<li>images/logo.png</li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/offline-webapps/#offline">http://www.w3.org/TR/offline-webapps/#offline</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/en/Offline_resources_in_Firefox">https://developer.mozilla.org/en/Offline_resources_in_Firefox</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+</strong><br />
<br/></p>
<h3>HTML5 Database Storage</h3>
<p>本地数据库，支持sql，最早是google gears实现，现在的w3c草案的编辑也是google的工程师……但奇怪的是，gears的api跟现在的草案不兼容，chrome甚至为了保留捆绑的gears的数据库api而删除了webkit实现的html5 api……而google在iphone上实现gmail离线功能的时候又采用webkit的api……真纠结……</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">db</span><span style="color: Gray;"> = </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">openDatabase</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">notes</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">The Example Notes App!</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Maroon;">1048576</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">db</span><span style="color: Gray;">.</span><span style="color: Blue;">transaction</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">tx</span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span></li>
<li><span style="color: Blue;">tx</span><span style="color: Gray;">.</span><span style="color: Blue;">executeSql</span><span style="color: Olive;">(</span><span style="color: Gray;">‘</span><span style="color: Blue;">SELECT</span><span style="color: Gray;"> * </span><span style="color: Blue;">FROM</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">Notes</span><span style="color: Gray;">’, </span><span style="color: Olive;">[]</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">tx</span><span style="color: Gray;">, </span><span style="color: Blue;">rs</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/offline-webapps/#sql">http://www.w3.org/TR/offline-webapps/#sql</a><br />
webkit博客的介绍：<a target="_blank"  href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/">http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/</a><br />
iphone的文档：<a target="_blank"  href="http://developer.apple.com/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/UsingtheJavascriptDatabase/UsingtheJavascriptDatabase.html#//apple_ref/doc/uid/TP40007256-CH3-SW1">http://developer.apple.com/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/UsingtheJavascriptDatabase/UsingtheJavascriptDatabase.html#//apple_ref/doc/uid/TP40007256-CH3-SW1</a></p>
<p><strong style="color:#ff6600;">支持：Safari 3.1+</strong><br />
<strong style="color:#ff6600;">替代/过渡：Gears <a target="_blank"  href="http://code.google.com/p/gears/wiki/Database2API">http://code.google.com/p/gears/wiki/Database2API</a></strong><br />
<br/></p>
<h3>HTML5 Web Workers</h3>
<p>多线程，在后台执行复杂运算，不能操作dom，线程之间通过消息事件通信</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">myWorker</span><span style="color: Gray;"> = </span><span style="color: Green;">new</span><span style="color: Gray;"> </span><span style="color: Blue;">Worker</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">my_worker.js</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">myWorker</span><span style="color: Gray;">.</span><span style="color: Blue;">onmessage</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">event</span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: Blue;">event</span><span style="color: Gray;">.</span><span style="color: Blue;">data</span><span style="color: Gray;"> </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">myWorker</span><span style="color: Gray;">.</span><span style="color: Blue;">postMessage</span><span style="color: Olive;">(</span><span style="color: Blue;">str</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/workers/">http://www.w3.org/TR/workers/</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/Using_web_workers">https://developer.mozilla.org/En/Using_web_workers</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+</strong><br />
<strong style="color:#ff6600;">替代/过渡：Gears <a target="_blank"  href="http://code.google.com/p/gears/wiki/HTML5WorkerProposal">http://code.google.com/p/gears/wiki/HTML5WorkerProposal</a></strong><br />
<br/></p>
<h3>HTML5 Geolocation</h3>
<p>地理api</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Teal;">navigator</span><span style="color: Gray;">.</span><span style="color: Blue;">geolocation</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/geolocation-API/">http://www.w3.org/TR/geolocation-API/</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/Using_geolocation">https://developer.mozilla.org/En/Using_geolocation</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+</strong><br />
<strong style="color:#ff6600;">替代/过渡：Gears <a target="_blank"  href="http://code.google.com/p/gears/wiki/GeolocationAPI">http://code.google.com/p/gears/wiki/GeolocationAPI</a></strong><br />
<br/></p>
<h3>HTML5 Drag and Drop</h3>
<p>原生拖拽事件</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">ondragstart</span></li>
<li><span style="color: Blue;">ondrag</span></li>
<li><span style="color: Blue;">ondragend</span></li>
<li><span style="color: #ffa500;">//拖拽过程中</span></li>
<li><span style="color: Blue;">ondragenter</span></li>
<li><span style="color: Blue;">ondragover</span></li>
<li><span style="color: Blue;">ondragleave</span></li>
<li><span style="color: Blue;">ondrop</span></li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/html5/editing.html#dnd">http://www.w3.org/TR/html5/editing.html#dnd</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/DragDrop/Drag_and_Drop">https://developer.mozilla.org/En/DragDrop/Drag_and_Drop</a><br />
apple文档：<a target="_blank"  href="http://developer.apple.com/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/DragAndDrop.html#//apple_ref/doc/uid/30001233">http://developer.apple.com/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/DragAndDrop.html#//apple_ref/doc/uid/30001233</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, Safari 2.0+, Chrome 1.0+, IE 5.0+</strong><br />
<br/></p>
<h3>HTML5 Audio and Video</h3>
<p>用html标签来嵌入视频音频的好处并非是“开源格式”，而是“开放性”，让多媒体可以与其他页面元素交互，或者<a target="_blank"  href="http://blog.mozbox.org/post/2009/04/12/Firefox-35:-a-new-experiment-with-Canvas-Video">用页面技术去跟视频“mashup”</a>，这种随意组合和交互的能力是web技术兴盛的基石，也是像flash这类封闭RIA容器最大的缺点。</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">video</span><span style="color: Gray;"> </span><span style="color: #00008b;">controls</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Olive;">&lt;</span><span style="color: Green;">source</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">src</span><span style="color: Gray;">=“</span><span style="color: #00008b;">zombie</span><span style="color: Gray;">.</span><span style="color: #00008b;">ogg</span><span style="color: Gray;">” </span><span style="color: #00008b;">type</span><span style="color: Gray;">=“</span><span style="color: #00008b;">video</span><span style="color: Gray;">/</span><span style="color: Green;">ogg</span><span style="color: Gray;">”</span><span style="color: Olive;">/&gt;</span></li>
<li><span style="color: Olive;">&lt;</span><span style="color: Green;">source</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">src</span><span style="color: Gray;">=“</span><span style="color: #00008b;">zombie</span><span style="color: Gray;">.</span><span style="color: #00008b;">mp4</span><span style="color: Gray;">″ </span><span style="color: #00008b;">type</span><span style="color: Gray;">=“</span><span style="color: #00008b;">video</span><span style="color: Gray;">/</span><span style="color: Green;">mp4</span><span style="color: Gray;">″</span><span style="color: Olive;">/&gt;</span></li>
<li><span style="color: Olive;">&lt;/</span><span style="color: Green;">video</span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox">https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox</a><br />
webkit博客的介绍：<a target="_blank"  href="http://webkit.org/blog/140/html5-media-support/">http://webkit.org/blog/140/html5-media-support/</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, Safari 3.0+, Chrome 3.0+</strong><br />
<strong style="color:#ff6600;">替代/过渡：用video标签嵌套embed <a target="_blank"  href="http://hacks.mozilla.org/2009/06/html5-video-fallbacks-markup/">http://hacks.mozilla.org/2009/06/html5-video-fallbacks-markup/</a></strong><br />
<br/></p>
<h3>HTML5 Canvas</h3>
<p>apple发明，最早应用于dashboard，目前主流的js图像技术，mozilla已经在实现OpenGL ES标准的<a target="_blank"  href="http://blog.vlad1.com/2007/11/26/canvas-3d-gl-power-web-style/">Canvas 3D</a>了，另外据说ie team为支持canvas<a target="_blank"  href="http://processingjs.org/blog/?p=77">做了大量工作</a>……实际上canvas api相当底层，特别是交互方面，不如svg直观，所以出现了很多封装它的库</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">ctx</span><span style="color: Gray;"> = $</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">#canvas</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)[</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">.</span><span style="color: Blue;">getContext</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">2d</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">ctx</span><span style="color: Gray;">.</span><span style="color: Blue;">fillStyle</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">#00A308</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">ctx</span><span style="color: Gray;">.</span><span style="color: Blue;">beginPath</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">ctx</span><span style="color: Gray;">.</span><span style="color: Blue;">arc</span><span style="color: Olive;">(</span><span style="color: Maroon;">220</span><span style="color: Gray;">, </span><span style="color: Maroon;">220</span><span style="color: Gray;">, </span><span style="color: Maroon;">50</span><span style="color: Gray;">, </span><span style="color: Maroon;">0</span><span style="color: Gray;">, </span><span style="color: Teal;">Math</span><span style="color: Gray;">.</span><span style="color: Blue;">PI</span><span style="color: Gray;">*</span><span style="color: Maroon;">2</span><span style="color: Gray;">, </span><span style="color: Green;">true</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">ctx</span><span style="color: Gray;">.</span><span style="color: Blue;">closePath</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">ctx</span><span style="color: Gray;">.</span><span style="color: Blue;">fill</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li></ol></div>
<p>MDC文档：<a target="_blank"  href="https://developer.mozilla.org/en/Canvas_tutorial">https://developer.mozilla.org/en/Canvas_tutorial</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 1.5+, Safari 2.0+, Chrome 1.0+, Opera 9.0+</strong><br />
<strong style="color:#ff6600;">替代/过渡：excanvas.js <a target="_blank"  href="http://code.google.com/p/explorercanvas/">http://code.google.com/p/explorercanvas/</a></strong><br />
<br/></p>
<h3>SVG</h3>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/SVG12/">http://www.w3.org/TR/SVG12/</a><br />
IBM DW教程：<a target="_blank"  href="http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84896">http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84896</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 1.5+, Safari 3.0+, Chrome 1.0+, Opera 9.0+</strong><br />
<strong style="color:#ff6600;">替代/过渡：raphael.js <a target="_blank"  href="http://raphaeljs.com/">http://raphaeljs.com/</a></strong><br />
<br/></p>
<h3>XMLHttpRequest 2</h3>
<p>主要是增加跨域能力以及请求过程中的事件</p>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/XMLHttpRequest2/">http://www.w3.org/TR/XMLHttpRequest2/</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/Using_XMLHttpRequest#Monitoring_progress">https://developer.mozilla.org/En/Using_XMLHttpRequest#Monitoring_progress</a><br />
XDomainRequest (XDR)<br />
MSDN文档：<a target="_blank"  href="http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx">http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+（实现了部分）, IE 8.0+（实现了部分）</strong><br />
<br/></p>
<h3>Access Control</h3>
<p>千呼万唤的跨域访问控制，目前firefox3.5和ie8有一些不同，ie8搞的XDR和XDM我也不知道是不是准备提交给w3c标准化的东西……</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">Access-Control-Allow-Origin: http://foo.example</li></ol></div>
<p>w3c标准：<a target="_blank"  href="http://www.w3.org/TR/cors/">http://www.w3.org/TR/cors/</a><br />
MDC文档：<a target="_blank"  href="https://developer.mozilla.org/En/HTTP_Access_Control">https://developer.mozilla.org/En/HTTP_Access_Control</a><br />
Cross-document Messaging (XDM)<br />
MSDN文档：<a target="_blank"  href="http://msdn.microsoft.com/en-us/library/cc197057(VS.85).aspx">http://msdn.microsoft.com/en-us/library/cc197057(VS.85).aspx</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, IE8.0+</strong><br />
<br/></p>
<h3>E4X (ECMA-357)</h3>
<p>Firefox和ActionScript3早就实现了的东西……不过其实现在json这么流行，有没有E4X好像都无所谓了～（瞎说的，其实在js代码里直接写dom对象而不是html字符串，会方便很多）</p>
<p>MDC文档：<a target="_blank"  href="https://developer.mozilla.org/en/E4X">https://developer.mozilla.org/en/E4X</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 1.5+</strong><br />
<br/></p>
<h3>ECMAScript 5  Native JSON</h3>
<p>原生的JSON支持，速度和安全性都比eval强一百倍亚一百倍，另外要注意Douglas Crockford的json2.js是一个用js实现的js解释器，所以安全性更好</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">JSON</span><span style="color: Gray;">.</span><span style="color: Blue;">parse</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">text</span><span style="color: Gray;">, </span><span style="color: Blue;">translate</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Blue;">JSON</span><span style="color: Gray;">.</span><span style="color: Blue;">stringify</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">, </span><span style="color: Blue;">translate</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Teal;">String</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">toJSON</span></li>
<li><span style="color: Blue;">Boolean</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">toJSON</span></li>
<li><span style="color: Teal;">Number</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">toJSON</span></li>
<li><span style="color: Teal;">Date</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">toJSON</span></li></ol></div>
<p>MDC文档：<a target="_blank"  href="http://blog.mozilla.com/webdev/2009/02/12/native-json-in-firefox-31/">http://blog.mozilla.com/webdev/2009/02/12/native-json-in-firefox-31/</a><br />
MSDN文档：<a target="_blank"  href="http://blogs.msdn.com/ie/archive/2008/09/10/native-json-in-ie8.aspx">http://blogs.msdn.com/ie/archive/2008/09/10/native-json-in-ie8.aspx</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 3.5+, IE8+</strong><br />
<strong style="color:#ff6600;">替代/过渡：json2.js <a target="_blank"  href="http://www.json.org/json2.js">http://www.json.org/json2.js</a></strong><br />
<br/></p>
<h3>ECMAScript 5  Array Extras</h3>
<p>js1.6里实现的数组方法，主要是forEach, map, fliter这几个函数式编程里非常重要的方法，还有反向查询</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">indexOf</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">str</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">lastIndexOf</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">str</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">every</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fn</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">some</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fn</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">filter</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fn</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">forEach</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fn</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">map</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fn</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li></ol></div>
<p>MDC文档：<a target="_blank"  href="https://developer.mozilla.org/en/New_in_JavaScript_1.6#Array_extras">https://developer.mozilla.org/en/New_in_JavaScript_1.6#Array_extras</a></p>
<p><strong style="color:#ff6600;">支持：Firefox2.0+, Safari 3.0+, Google Chrome 1.0+, Opera 9.5+</strong><br />
<strong style="color:#ff6600;">替代/过渡：都可以通过扩展Array.prototype来模拟</strong><br />
<br/></p>
<h3>ECMAScript 5  isArray()</h3>
<p>区分数组和对象</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">Array</span><span style="color: Gray;">.</span><span style="color: Blue;">isArray</span><span style="color: Olive;">([])</span><span style="color: Gray;">; </span><span style="color: #ffa500;">// true</span></li></ol></div>
<p><strong style="color:#ff6600;">支持：无</strong><br />
<strong style="color:#ff6600;">替代/过渡：Array.isArray = function(a){ return Object.prototype.toString.call(a) === &#8220;[object Array]&#8220;;};</strong><br />
<br/></p>
<h3>ECMAScript 5  Object</h3>
<p>用GOOGLE I/O演讲里的话来说：更鲁棒(robust)的对象系统<br />
<br/></p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">getPrototypeOf</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li></ol></div>
<p>约翰同学的讲解：<a target="_blank"  href="http://ejohn.org/blog/objectgetprototypeof/">http://ejohn.org/blog/objectgetprototypeof/</a></p>
<p><strong style="color:#ff6600;">支持：Firefox3.5</strong><br />
<strong style="color:#ff6600;">替代/过渡：object.__proto__ 或 object.constructor.prototype</strong><br />
<br/></p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">create</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">proto</span><span style="color: Gray;">, </span><span style="color: Blue;">props</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//克隆或继承对象</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">keys</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//数据结构的映射</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">getOwnPropertyNames</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">preventExtensions</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//不能添加新属性</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">isExtensible</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">seal</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//不能删除和修改属性的配置，不能添加新属性</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">isSealed</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">freeze</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: #ffa500;">//不能删除和修改属性的配置，不能添加新属性，不能写属性</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">isFrozen</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li></ol></div>
<p>约翰同学的讲解：<a target="_blank"  href="http://ejohn.org/blog/ecmascript-5-objects-and-properties/">http://ejohn.org/blog/ecmascript-5-objects-and-properties/</a></p>
<p><strong style="color:#ff6600;">支持：无</strong><br />
<strong style="color:#ff6600;">替代/过渡：Object.create和Object.keys可以自己实现</strong><br />
<br/></p>
<h3>ECMAScript 5 Property Descriptor</h3>
<p>对象属性的访问控制</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">getOwnPropertyDescriptor</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">obj</span><span style="color: Gray;">, </span><span style="color: Blue;">prop</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">defineProperty</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">, </span><span style="color: Blue;">prop</span><span style="color: Gray;">, </span><span style="color: Blue;">desc</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">defineProperties</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">, </span><span style="color: Blue;">props</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">desc</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp;&nbsp; </span><span style="color: Blue;">value</span><span style="color: Gray;">: </span><span style="color: Green;">true</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp;&nbsp; </span><span style="color: Blue;">writable</span><span style="color: Gray;">: </span><span style="color: Green;">false</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//修改</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp;&nbsp; </span><span style="color: Blue;">enumerable</span><span style="color: Gray;">: </span><span style="color: Green;">true</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//for in</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp;&nbsp; </span><span style="color: Blue;">configurable</span><span style="color: Gray;">: </span><span style="color: Green;">true</span><span style="color: Gray;">, </span><span style="color: #ffa500;">//删除和修改属性</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp;&nbsp; </span><span style="color: Blue;">get</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">return</span><span style="color: Gray;"> </span><span style="color: Blue;">name</span><span style="color: Gray;">; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp;&nbsp; </span><span style="color: Blue;">set</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">value</span><span style="color: Olive;">){</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">name</span><span style="color: Gray;"> = </span><span style="color: Blue;">value</span><span style="color: Gray;">; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>约翰同学的讲解：<a target="_blank"  href="http://ejohn.org/blog/ecmascript-5-objects-and-properties/">http://ejohn.org/blog/ecmascript-5-objects-and-properties/</a></p>
<p><strong style="color:#ff6600;">支持：无</strong><br />
<strong style="color:#ff6600;">替代/过渡：Object.defineProperties其实相当于jQuery.extend，用来实现Mixin</strong><br />
<br/></p>
<h3>ECMAScript 5 Getters and Setters</h3>
<p>python和ruby里都有的属性访问方法</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">obj</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Blue;">get</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">innerHTML</span><span style="color: Olive;">()</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: Green;">return</span><span style="color: Gray;"> …; </span><span style="color: Olive;">}</span><span style="color: Gray;">, </span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Blue;">set</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">innerHTML</span><span style="color: Olive;">(</span><span style="color: Blue;">newHTML</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;"> … </span><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li></ol></div>
<p>MDC文档：<a target="_blank"  href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Creating_New_Objects/Defining_Getters_and_Setters">https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Creating_New_Objects/Defining_Getters_and_Setters</a></p>
<p><strong style="color:#ff6600;">支持：Firefox 2.0+, Safari 3.0+, Google Chrome 1.0+, Opera 9.5+</strong><br />
<strong style="color:#ff6600;">替代/过渡：</strong></p>
<p>非标准，Firefox1.5里的旧方法</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">HTMLElement</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">__defineGetter__</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">innerHTML</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Olive;">()</span><span style="color: Gray;"> </span><span style="color: Olive;">{})</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">HTMLElement</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">__defineSetter__</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">innerHTML</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">val</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{})</span><span style="color: Gray;">;</span></li></ol></div>
<p><strong style="color:#ff6600;">支持：Firefox 2.0+, Safari 3.0+, Google Chrome 1.0+, Opera 9.5+</strong></p>
<p>标准</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">Object</span><span style="color: Gray;">.</span><span style="color: Blue;">defineProperty</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">body</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">innerHTML</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: Blue;">get</span><span style="color: Gray;"> : </span><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Olive;">()</span><span style="color: Gray;"> </span><span style="color: Olive;">{}</span><span style="color: Gray;"> </span><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>MSDN文档：<a target="_blank"  href="http://msdn.microsoft.com/en-us/library/dd229916(VS.85).aspx">http://msdn.microsoft.com/en-us/library/dd229916(VS.85).aspx</a></p>
<p><strong style="color:#ff6600;">支持：IE8+ (只能对DOM使用)</strong><br />
<br/></p>
<h3>ECMAScript 5 Strict Mode</h3>
<p>ES5的严格模式，删除了旧版本中容易引起问题的元素，并且会显式的报错，方便调试</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #8b0000;">&quot;</span><span style="color: Red;">use strict</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//以下情况下抛出异常</span></li>
<li><span style="color: #ffa500;">//对未定义的变量赋值</span></li>
<li><span style="color: #ffa500;">//操作被设置为不可写，不可配置或不可扩充的属性</span></li>
<li><span style="color: #ffa500;">//删除变量，函数，参数</span></li>
<li><span style="color: #ffa500;">//在对象直接量里重复定义属性</span></li>
<li><span style="color: #ffa500;">//eval做关键字，在eval的字符串里定义变量</span></li>
<li><span style="color: #ffa500;">//覆写arguments</span></li>
<li><span style="color: #ffa500;">//使用arguments.caller和arguments.callee（匿名函数必须具名才能引用自己）</span></li>
<li><span style="color: #ffa500;">//(function(){ ... }).call( null ); // Exception </span></li>
<li><span style="color: #ffa500;">//使用with</span></li></ol></div>
<p>约翰同学的讲解：<a target="_blank"  href="http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/">http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/</a></p>
<p><strong style="color:#ff6600;">支持：无</strong><br />
<strong style="color:#ff6600;">替代/过渡：……从现在开始养成严谨的编程习惯</strong><br />
<br/></p>
<h3>ECMAScript 5 其他新特性</h3>
<p>传递函数的引用时，绑定this</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">Function</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">bind</span><span style="color: Olive;">(</span><span style="color: Blue;">thisArg</span><span style="color: Gray;">, </span><span style="color: Blue;">arg1</span><span style="color: Gray;">, </span><span style="color: Blue;">arg2</span><span style="color: Gray;">....</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: #8b0000;">/</span></li></ol></div>
<p><strong style="color:#ff6600;">支持：无</strong><br />
<strong style="color:#ff6600;">替代/过渡：prototype <a target="_blank"  href="http://www.prototypejs.org/api/function/bind">http://www.prototypejs.org/api/function/bind</a></strong></p>
<p>ISO-formatted dates</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">Date</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">toISOString</span><span style="color: Olive;">()</span><span style="color: Gray;"> </span><span style="color: #ffa500;">// Prints 2009-05-21T16:06:05.000TZ</span></li></ol></div>
<p><strong style="color:#ff6600;">支持：无</strong><br />
<strong style="color:#ff6600;">替代/过渡：datejs <a target="_blank"  href="http://code.google.com/p/datejs/">http://code.google.com/p/datejs/</a></strong></p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">String</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">trim</span><span style="color: Olive;">()</span></li></ol></div>
<p><strong style="color:#ff6600;">支持：Firefox3.5</strong><br />
<strong style="color:#ff6600;">替代/过渡：各种正则实现 <a target="_blank"  href="http://blog.stevenlevithan.com/archives/faster-trim-javascript">http://blog.stevenlevithan.com/archives/faster-trim-javascript</a></strong><br />
<br/><br />
===================废话又开始的分割线=======================</p>
<p>其实我把这个东西发出来是希望能促进创新的氛围，让更多人认识到很多新技术已经进入到“实用”阶段。</p>
<p>如果只是想做个实验性的webgame，或是只能用于特定平台的应用（比如iphone，greasemonkey），firefox3.5+webkit的支持就已经足够罢。</p>
<p>如果不能无视主流平台，有很多技术能让你gracefully degrade（优雅的退化）或者选取不同的方法实现兼容的接口。</p>
<p>如果你等不及IE x在若干年后实现xx，希望提前享受福利，有些技术的设计原则就是让你能在没有native支持的情况下可以自己实现一模一样的功能或语法糖（syntactic sugar），比如ES5对象的继承和访问控制，从ES4/ActionScript3时期那些老土的关键词（class extands private static）改成了Object.create(p, attrs).defineProperty(o, n, attrs).defineProperties(o, attrs).freeze().getOwnPropertyNames().map(fn)，不会只是为了酷炫罢……</p>
<p>很多人都喜欢抱怨“我这辈子都没机会用HTML5”，但是只要把视线从自己脚下那巴掌大块地移开看看别处，会发现世界其实一直都在改变喔XD</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/06/29/html5-css3-es5-support/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>继续补充vim配置技巧——上次的vimrc还不够强力</title>
		<link>http://www.limboy.com/2009/06/07/vim-setting-more/</link>
		<comments>http://www.limboy.com/2009/06/07/vim-setting-more/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 18:52:27 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[OpenSource]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[工具]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/06/07/vim-setting-more/</guid>
		<description><![CDATA[首先要补充一些MacVim的配置，其实写上篇文章的时候我还在用已经过时的基于Carbon界面的vim for osx，更接近传统的unix版本，但是好久没更新，只支持vim6.0，soureforge上有一个7.2的版本，bug诸多，其中的乱码和字体抗锯齿的问题让我完全无法忍。而MacVim是基于Cocoa开发，支持到7.2，还含有很多讨好mac用户的设计，比如对标签的良好支持，华丽的界面（背景颜色支持透明度，字体抗锯齿更漂亮，几乎跟TextMate的效果没区别）……非常后悔以前没仔细试用这个版本！目前为止只发现行高linespace的设置会无法生效，不过这个bug在最新的快照版里已经修正了。
插播一个道歉：由于spam太多，我前段时间在wordpress黑名单里加了一个很苛刻的条件，把所有评论都挡到待审核列表里去了，好像还直接删了一部分……咳……
我在.vimrc里增加了一些专门针对MacVim的设置：
if has(&#34;gui_macvim&#34;)
&#160; &#34;取消默认的快捷键
&#160; let macvim_skip_cmd_opt_movement = 1 
&#160; let macvim_hig_shift_movement = 1
&#160; 
&#160; &#34;设置背景透明度
&#160; set transparency=2
&#160; &#34;隐藏工具条
&#160; set guioptions-=T &#34;egmrt
&#160; 
&#160; &#34;绑定自己需要的cmd快捷键
&#160; macm File.Save&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; key=&#60;D-s&#62;
&#160; macm File.Save\ As\.\.\.&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; key=&#60;D-S&#62;
&#160; macm [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2009/06/picture-4.png' title='picture-4.png' target="_blank"><img src='http://www.limboy.com/wp-content/uploads/2009/06/picture-4.png' alt='picture-4.png' style="width:200px;margin:0 10px 10px 0;float:left;" /></a>首先要补充一些<a href="http://code.google.com/p/macvim/" target="_blank">MacVim</a>的配置，其实写上篇文章的时候我还在用已经过时的<a href="http://macvim.org/OSX/index.php" target="_blank">基于Carbon界面的vim for osx</a>，更接近传统的unix版本，但是好久没更新，只支持vim6.0，soureforge上有一个<a href="http://sourceforge.net/project/showfiles.php?group_id=213254" target="_blank">7.2的版本</a>，bug诸多，其中的乱码和字体抗锯齿的问题让我完全无法忍。而MacVim是基于Cocoa开发，支持到7.2，还含有很多讨好mac用户的设计，比如对标签的良好支持，华丽的界面（背景颜色支持透明度，字体抗锯齿更漂亮，几乎跟TextMate的效果没区别）……非常后悔以前没仔细试用这个版本！目前为止只发现行高linespace的设置会无法生效，不过这个bug在<a href="http://code.google.com/p/macvim/wiki/Snapshot" target="_blank">最新的快照版</a>里已经修正了。</p>
<p>插播一个道歉：由于spam太多，我前段时间在wordpress黑名单里加了一个很苛刻的条件，把所有评论都挡到待审核列表里去了，好像还直接删了一部分……咳……<span id="more-236"></span></p>
<p>我在.vimrc里增加了一些专门针对MacVim的设置：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">if has(&quot;gui_macvim&quot;)</li>
<li>&nbsp; &quot;取消默认的快捷键</li>
<li>&nbsp; let macvim_skip_cmd_opt_movement = 1 </li>
<li>&nbsp; let macvim_hig_shift_movement = 1</li>
<li>&nbsp; </li>
<li>&nbsp; &quot;设置背景透明度</li>
<li>&nbsp; set transparency=2</li>
<li>&nbsp; &quot;隐藏工具条</li>
<li>&nbsp; set guioptions-=T &quot;egmrt</li>
<li>&nbsp; </li>
<li>&nbsp; &quot;绑定自己需要的cmd快捷键</li>
<li>&nbsp; macm File.Save&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key=&lt;D-s&gt;</li>
<li>&nbsp; macm File.Save\ As\.\.\.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key=&lt;D-S&gt;</li>
<li>&nbsp; macm Edit.Undo&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key=&lt;D-z&gt; action=undo:</li>
<li>&nbsp; macm Edit.Redo&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key=&lt;D-Z&gt; action=redo:</li>
<li>&nbsp; macm Edit.Cut&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;key=&lt;D-x&gt; action=cut:</li>
<li>&nbsp; macm Edit.Copy&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key=&lt;D-c&gt; action=copy:</li>
<li>&nbsp; macm Edit.Paste&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;key=&lt;D-v&gt; action=paste:</li>
<li>&nbsp; macm Edit.Select\ All&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;key=&lt;D-A&gt; action=selectAll:</li>
<li>endif</li></ol></div>
<p>之所以要取消MacVim默认的一些快捷键是因为它们都占用了cmd苹果键，而我习惯用这个键来替代ctrl在vim里的作用（在mbp的键盘上就算我想用ctrl也不方便……），不过其中有几个快捷键是非常非常有价值的，比如保存（省去了输入:w的麻烦），全选（否则要摁六下：ggVG），复制粘贴剪切（否则为了使用剪贴板，比如猛摁这种玩意：&#8221;+y，还不能在插入模式下使用 ），幸好它们的快捷键都不跟vim其他操作冲突，所以自己设置。为了完全删除MacVim默认的cmd快捷键，还需要打开app中自带的vimrc文件（可以这样编辑：:tabe $VIM/vimrc ），删除末尾那些macm开头的代码。<br />
<br/><br />
MacVim的安装包里包含一个mvim，是像gvim一样的脚本，用来在命令行中调用GUI版的vim，但是mvim默认会在新窗口打开文件，我相信多数人都喜欢在当前窗口的新标签页里打开罢，需要在命令后加&#8211;remote-tab参数，不过<a href="http://webexpose.org/2008/10/13/open-macvim-tabs-from-command-line" target="_blank">这篇文章</a>里给出了直接修改脚本的方法，把mvim底部从# Last step:  fire up vim开始的部分删掉，改成：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">tabs=true </li>
<li>&nbsp;</li>
<li># Last step:&nbsp; fire up vim. </li>
<li>if [ &quot;$gui&quot; ]; then </li>
<li>	if $tabs &amp;&amp; [[ `$binary --serverlist` = &quot;VIM&quot; ]]; then</li>
<li>	&nbsp; &nbsp;	exec &quot;$binary&quot; -g $opts --remote-tab-silent ${1:+&quot;$@&quot;} </li>
<li>	else </li>
<li>		exec &quot;$binary&quot; -g $opts ${1:+&quot;$@&quot;} </li>
<li>	fi </li>
<li>else </li>
<li>	exec &quot;$binary&quot; $opts ${1:+&quot;$@&quot;} </li>
<li>fi</li></ol></div>
<p>P.S. 上面给出的那个blog不能直接打开，也许是需要翻墙，不过我顺便介绍一个很方便的利用google网页快照的方法～ 用<a href="http://translate.google.cn/translate_t#zh-CN|en|" target="_blank">谷歌翻译</a>打开这个网址 XD<br />
<br/><br />
刚安装好的MacVim打开gb编码的文件仍然把中文显示成乱码（好无奈，GBK编码是土豆网的历史遗留问题，页面里的script标签也几乎都没加charset=&#8221;utf-8&#8243;，所以大部分js文件都只好用gb18030的编码，textmate正是因为不支持gb编码才被我降为二等公民的，其实我有正版cdkey……），我在.vimrc里加上了encoding似乎能解决这个问题：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">set encoding=utf-8</li>
<li>set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936</li></ol></div>
<p>解释一下：对于编码，vim里有三个设置选项，encoding是设置vim以何种编码显示文件（缩写enc），fileencoding是当前文件实际的编码（缩写fenc）， 而fileencodings指示vim如何解码（缩写fencs），因此vim在打开一个文件时实际上会先根据fileencodings里的列表反复测试，直到成功解码，转换成encoding指定的编码，然后正常显示，转码的过程是用iconv实现的（所以windows上用vim还要配置iconv的dll路径和参数……麻烦），保存的时候会根据fileencoding来保存，跟是否显示为乱码没有关系。</p>
<p>所以如果想转换一个文件的编码，比如从utf-8转换到gb18030，可以在编辑器中直接输入两个命令：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">:set enc=gb18030</li>
<li>:set fenc=gb18030</li></ol></div>
<p>然后保存就ok了～其实如果不用继续编辑的话，第一行都可以省去，因为它的目的只是让编辑器用gb18030来显示当前文件，避免乱码，但是并不影响文件保存时的编码和正确性。</p>
<p>以前我都是依赖mac上的<a href="http://www.panic.com/coda/" target="_blank">Coda</a>来转换编码（确实最方便）……vim又成功了抢了它的饭碗……<br />
<br/><br />
MacVim还有一个问题是会显示一个很宅很不人性的标签栏名称，比如我编辑/usr/local/bin/mvim这个文件，标签栏上写的是“/u/l/b/mvim”，如果目录结构再深一点就看不到真正的文件名了，在.vimrc里加入下面这行可以让标签栏只显示文件名：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">set guitablabel=%t</li></ol></div>
<p><br/><br />
上次的.vimrc里还增加了两处很重要的设置，主要是受这位老爷写的<a href="http://easwy.com/blog/archives/advanced-vim-skills-catalog/" target="_blank">《vim使用进阶》</a>的启发，首先是让.vimrc每次编辑保存后自动生效，避免重启：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">autocmd! bufwritepost .vimrc source ~/.vimrc</li></ol></div>
<p>autocmd实际上是vim脚本的事件机制，表示在某个事件触发后自动执行的命令<br />
<br/><br />
接下来要实现的是保存和恢复编辑器的当前状态，类似Eclipse的Workspace，不过vim的session更强大，几乎可以还原一切状态……<a href="http://easwy.com/blog/archives/advanced-vim-skills-session-file-and-viminfo/" target="_blank">Easwy老爷介绍的命令</a>比较繁琐，缺乏“一键恢复”的快感……身为一个习惯使用“高级语言”的程序员，在这种时候就抑制不住继续封装和提高抽象层的欲望……所以自定义了以下两个命令：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">function! GetMySession(spath, ssname)</li>
<li>	if a:ssname == 0</li>
<li>		let a:sname = &quot;&quot;</li>
<li>	else</li>
<li>		let a:sname = &quot;-&quot;.a:ssname</li>
<li>	endif</li>
<li>	execute &quot;source $&quot;.a:spath.&quot;/session&quot;.a:sname.&quot;.vim&quot;</li>
<li>	execute &quot;rviminfo $&quot;.a:spath.&quot;/session&quot;.a:sname.&quot;.viminfo&quot;</li>
<li>	execute &quot;echo \&quot;Load Success\: $&quot;.a:spath.&quot;/session&quot;.a:sname.&quot;.vim\&quot;&quot;</li>
<li>endfunction</li>
<li>&nbsp;</li>
<li>function! SetMySession(spath, ssname)</li>
<li>	if a:ssname == 0</li>
<li>		let a:sname = &quot;&quot;</li>
<li>	else</li>
<li>		let a:sname = &quot;-&quot;.a:ssname</li>
<li>	endif</li>
<li>	execute &quot;cd $&quot;.a:spath</li>
<li>	execute &quot;mksession! $&quot;.a:spath.&quot;/session&quot;.a:sname.&quot;.vim&quot;</li>
<li>	execute &quot;wviminfo! $&quot;.a:spath.&quot;/session&quot;.a:sname.&quot;.viminfo&quot;</li>
<li>	execute &quot;echo \&quot;Save Success\: $&quot;.a:spath.&quot;/session&quot;.a:sname.&quot;.vim\&quot;&quot;</li>
<li>endfunction</li>
<li>&nbsp;</li>
<li>&quot; load session from certain path</li>
<li>command! -nargs=+ LOAD call GetMySession(&lt;f-args&gt;) </li>
<li>&nbsp;</li>
<li>&quot; load session from certain path</li>
<li>command! -nargs=+ SAVE call SetMySession(&lt;f-args&gt;)</li></ol></div>
<p>为了用最简单的方法选择路径，使用时需要先在终端的初始化脚本（比如~/.bashrc，在我的OSX系统里通常用~/.profile）里添加相应的环境变量，比如我常用的三个路径：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">export TUISVN=&quot;/Users/dexteryy/Sites/Tudou/ui/ui/&quot;</li>
<li>export TUIDEV=&quot;/Volumes/ui.tudou.com/&quot;</li>
<li>export MYWEB=&quot;/Users/dexteryy/Sites/www/&quot;</li></ol></div>
<p>当我在MYWEB的路径下做项目的时候，如果需要保存当前状态，只要输入:SAVE MYWEB 0就行了，这里的0是因为考虑到在同一个工作目录里可能需要使用到不同文件组合的工作区，提供的一个简单的版本号，这段命令执行后会在/Users/dexteryy/Sites/www/目录里生成两个文件： session.viminfo和session.vim，如果版本号是大于0的整数，比如2，文件名会是session2.viminfo和session2.viminfo</p>
<p>需要恢复的时候只要输入命令：:LOAD MYWEB 0  就行叻～</p>
<p>喔对了，为了能在VIM命令里使用bash中定义的变量，你需要在MacVim的preferences里把“Launch Vim processes in a login shell”勾选，熟悉Mac应用的同学应该都能想到这个设置会记录在/Library/Preferences/或~/Library/Preferences/里的某个配置文件里，MacVim对应的是~/Library/Preferences/org.vim.MacVim.plist，所以你也可以直接用这个命令在终端里修改：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">defaults write org.vim.MacVim MMLoginShell 1</li></ol></div>
<p>如果使用的是Gvim或windows版本的vim，也可以直接把路径变量写在.vimrc里，比如：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">let g:TUISVN=&quot;/Users/dexteryy/Sites/Tudou/ui/ui/&quot;</li></ol></div>
<p>然后修改上面的两个函数GetMySession和SetMySession，把a:spath前面的$都删掉…………因为VIM里的变量只能由大写字母开头……</p>
<p>完整的<a href="http://code.google.com/p/yy-vimscript/source/browse/trunk/vimrc">.vimrc</a>在这里…………呃好罢我发现google code真是备份和维护配置脚本的好地方XD<br />
<br/><br />
最后继续讨论一下插件～</p>
<p>首先是<a href="http://www.vim.org/scripts/script.php?script_id=273" target="_blank">Taglist</a>，这是一个能让vim具备类似Aptana的<a href="http://aptana.com/docs/index.php/Displaying_the_Outline_View" target="_blank">Outline View</a>的功能，还能像JAVA的IDE那样通过类名和方法名直接跳转到相应的源码，它借助了一个叫ctags的工具，可以解析源码生成标签文件（在同一个名录下，叫tags），详细的介绍请参考<a href="http://easwy.com/blog/archives/advanced-vim-skills-use-ctags-tag-file/" target="_blank">Easwy老爷的文章</a>，记得务必安装最新版的Exuberant Ctags……我是用MacPorts装的：sudo port install ctags</p>
<p>Exuberant Ctags号称支持34种语言，包括javascript，但是它对javascript的理解非常OUT……比如现在定义JS方法几乎主要依靠匿名函数了，ctags却无法识别这种形式……</p>
<p>已经<a href="http://weblogs.asp.net/george_v_reilly/archive/2009/03/24/exuberant-ctags-and-javascript.aspx" target="_blank">有人</a>在尝试自己添加匹配规则，我自己也写了一大坨：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">--langdef=js</li>
<li>--langmap=js:.js</li>
<li>--regex-js=/[ \t.]([A-Z][A-Z0-9._$]+)[ \t]*=[ \t]*[0-9&quot;'\[\{]/\1/n,constant/</li>
<li>--regex-js=/([A-Za-z0-9._$]+)[ \t]*=[ \t]*\{/\1/o,object/</li>
<li>--regex-js=/['&quot;]*([A-Za-z0-9_$]+)['&quot;]*[ \t]*:[ \t]*\{/\1/o,object/</li>
<li>--regex-js=/([A-Za-z0-9._$]+)\[[&quot;']([A-Za-z0-9_$]+)[&quot;']\][ \t]*=[ \t]*\{/\1\.\2/o,object/</li>
<li>--regex-js=/([A-Za-z0-9._$]+)\.prototype[ \t.=]/\1/c,class/</li>
<li>--regex-js=/([A-Za-z0-9._$]+)[ \t]*=[ \t]*\(function\(\)/\1/c,class/</li>
<li>--regex-js=/['&quot;]*([A-Za-z0-9_$]+)['&quot;]*:[ \t]*\(function\(\)/\1/c,class/</li>
<li>--regex-js=/var[ \t]*([A-Za-z$][A-Za-z0-9_$()]+)[ \t]*=[ \t]*function[ \t]*\(/\1/f,function/</li>
<li>--regex-js=/function[ \t]+([A-Za-z$][A-Za-z0-9_$]+)[ \t]*\(([^)])\)/\1/f,function/</li>
<li>--regex-js=/['&quot;]*([A-Za-z$][A-Za-z0-9_$]+)['&quot;]*:[ \t]*function[ \t]*\(/\1/m,method/</li>
<li>--regex-js=/([A-Za-z$][A-Za-z0-9_$]+)[ \t]*=[ \t]*function[ \t]*\(/\1/m,method/</li>
<li>--regex-js=/([A-Za-z0-9_$]+)\[[&quot;']([A-Za-z0-9_$]+)[&quot;']\][ \t]*=[ \t]*function[ \t]*\(/\2/m,method/</li>
<li>--regex-js=/([A-Za-z0-9._$]+)[ \t]*=[ \t]*\[/\1/a,array/</li>
<li>--regex-js=/['&quot;]*([A-Za-z$][A-Za-z0-9_$]+)['&quot;]*:[ \t]*\[/\1/a,array/</li>
<li>--regex-js=/([A-Za-z0-9._$]+)\[[&quot;']([A-Za-z0-9_$]+)[&quot;']\][ \t]*=[ \t]*\[/\1\.\2/a,array/</li></ol></div>
<p>匹配以下语法形式，其中粗体部分是标签名称：</p>
<ol>
<li>var <strong>MY_CONSTANT</strong> = 250; //constant</li>
<li><strong>ns.myobject</strong> = {}; //object</li>
<li><strong>myobject</strong>: {}, //object</li>
<li>ns["myobject"] = {}; //object, 生成的tag是&#8221;<strong>ns.myobject</strong>&#8220;</li>
<li><strong>ns.myclass</strong>.prototype.myfunc = function(){}; //class</li>
<li><strong>ns.myclass </strong>= (function(){return {};}); //class</li>
<li>ns["myclass"] = (function(){return {};}); //class, 生成的tag是&#8221;<strong>ns.myclass</strong>&#8220;</li>
<li>var <strong>myfunc</strong> = function(){}; //function, 必须有var, _开头的忽略</li>
<li>function <strong>myfunc</strong>(){}; //function</li>
<li><strong>myfunc</strong>: function(){} //method</li>
<li>ns.<strong>myfunc</strong> = function(){}; //method</li>
<li>ns["myfunc"] = function(){}; //method, 生成的tag是&#8221;ns.<strong>myfunc</strong>&#8220;</li>
<li><strong>ns.myarray</strong> = []; //array</li>
<li><strong>myarray</strong>: [], //array</li>
<li>ns["myarray"] = []; //array, 生成的tag是&#8221;<strong>ns.myarray</strong>&#8220;</li>
</ol>
<p>使用方法是建一个~/.ctags文件，把上面那段代码放进去就行。为了在taglist窗口里显示类别（比如class和method），还需要在.vimrc里设置一个变量：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">let g:tlist_javascript_settings = 'javascript;f:function;c:class;o:object;m:method;s:string;a:array;n:constant'</li></ol></div>
<p><br/><br />
另一个要强烈推荐的插件是<a href="http://www.vim.org/scripts/script.php?script_id=1218" target="_blank">NERD Commenter</a>，从名字能看出跟上次推荐的NERD Tree是同一个强者写的，功能是针对各种文件类型快速的添加和删除注释，除了单行，多行，还提供“sexily”的注释……比如js里添加文档内容时常用的那种（如果首行写成/**，在aptana里会认作script doc格式）</p>
<p>不过这个插件默认使用了大量,c开头的快捷键……而,在vim里一般都用作自定义的<leader>键（<leader>的默认值是\，很显然小拇指没食指方便……），我没有找到相关的设置选项……所以直接<a href="http://code.google.com/p/yy-vimscript/source/diff?spec=svn7&#038;r=7&#038;format=side&#038;path=/trunk/plugin/NERD_commenter.vim" target="_blank">修改</a>了插件脚本……<br />
<br/><br />
唔唔就先写到这里罢，虽然vim无论日常使用还是hack都很爽，但是写起来还是挺枯燥的，头有点晕555……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/06/07/vim-setting-more/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>面向前端开发者和TextMate粉丝的vim配置</title>
		<link>http://www.limboy.com/2009/05/30/vim-setting/</link>
		<comments>http://www.limboy.com/2009/05/30/vim-setting/#comments</comments>
		<pubDate>Sat, 30 May 2009 14:21:23 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[OpenSource]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[工具]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/05/30/vim-setting/</guid>
		<description><![CDATA[vim是编辑器中的神器，但是因为学习曲线比较陡，界面也仿佛从石器时代穿越，广大fashion的前端工作者们难免对其有距离感。其实vim最大的萌点有两个，其一是百科全书般的文本编辑功能，其二是可以随意定制，满足任何与编辑器相关的需求和偏好，比如下面这张便是我在macbook pro上运行vim的截图，不仅语法高亮可以冒充TextMate，功能也几乎一致。

首先是做一个初始化配置脚本，在我的OSX10.5里是是~/.vimrc文件，这里只列出一些需要补充进去的设置：
&#34;设置语法高亮的配色，在GUI界面里使用我自定义的yytextmate.vim
if has(&#34;gui_running&#34;)
	colorscheme yytextmate
else
	colorscheme slate
endif
&#34;查找编码的规则（vim7默认都用utf-8，打开包含gbk字符的文件会出现乱码）
set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936
&#34;GUI界面里的字体，默认有抗锯齿
set guifont=Monaco:h12:cANSI
&#34;行间距，如果默认值太小，代码会非常纠结
set linespace=4&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;
&#34;用&#60;&#62;调整缩进时的长度
set shiftwidth=4 
&#34;制表符的长度，统一为4个空格的宽度
set tabstop=4
&#34;初始窗口的宽度
set columns=195
&#34;初始窗口的高度
set lines=45
&#34;初始窗口的位置
winpos 52 42
&#160;
&#34;显示行号
set number
&#34;行号栏的宽度
set numberwidth=4
&#160;&#34;禁止自动换行
set nowrap
&#34;在输入命令时列出匹配项目，也就是截图底部的效果
set wildmenu
&#34;显示光标位置
set ruler
&#34;分割窗口时保持相等的宽/高
set [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2009/05/30/vim-setting/vim-editor-icon1png/' rel='attachment wp-att-235' title='vim-editor-icon1.png'><img src='http://www.limboy.com/wp-content/uploads/2009/05/vim-editor-icon1.png' alt='vim-editor-icon1.png' style="float:left;border:0;margin:0 0 0px 10px;" /></a><a href='http://www.limboy.com/wp-content/uploads/2009/05/textmate.png' title='textmate.png'><img src='http://www.limboy.com/wp-content/uploads/2009/05/textmate.png' alt='textmate.png' style="float:left;border:0;margin:0 10px 0px 0px;" /></a>vim是编辑器中的神器，但是因为学习曲线比较陡，界面也仿佛从石器时代穿越，广大fashion的前端工作者们难免对其有距离感。其实vim最大的萌点有两个，其一是百科全书般的文本编辑功能，其二是可以随意定制，满足任何与编辑器相关的需求和偏好，比如下面这张便是我在macbook pro上运行vim的截图，不仅语法高亮可以冒充<a href="http://macromates.com/" target="_blank">TextMate</a>，功能也几乎一致。<span id="more-230"></span></p>
<p><a href='http://www.limboy.com/wp-content/uploads/2009/05/picture-4.png' title='picture-4.png'><img src='http://www.limboy.com/wp-content/uploads/2009/05/picture-4.png' alt='picture-4.png' style="width:400px;" /></a></p>
<p>首先是做一个初始化配置脚本，在我的OSX10.5里是是~/.vimrc文件，这里只列出一些需要补充进去的设置：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">&quot;设置语法高亮的配色，在GUI界面里使用我自定义的yytextmate.vim</li>
<li>if has(&quot;gui_running&quot;)</li>
<li>	colorscheme yytextmate</li>
<li>else</li>
<li>	colorscheme slate</li>
<li>endif</li>
<li>&quot;查找编码的规则（vim7默认都用utf-8，打开包含gbk字符的文件会出现乱码）</li>
<li>set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936</li>
<li>&quot;GUI界面里的字体，默认有抗锯齿</li>
<li>set guifont=Monaco:h12:cANSI</li>
<li>&quot;行间距，如果默认值太小，代码会非常纠结</li>
<li>set linespace=4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</li>
<li>&quot;用&lt;&gt;调整缩进时的长度</li>
<li>set shiftwidth=4 </li>
<li>&quot;制表符的长度，统一为4个空格的宽度</li>
<li>set tabstop=4</li>
<li>&quot;初始窗口的宽度</li>
<li>set columns=195</li>
<li>&quot;初始窗口的高度</li>
<li>set lines=45</li>
<li>&quot;初始窗口的位置</li>
<li>winpos 52 42</li>
<li>&nbsp;</li>
<li>&quot;显示行号</li>
<li>set number</li>
<li>&quot;行号栏的宽度</li>
<li>set numberwidth=4</li>
<li>&nbsp;&quot;禁止自动换行</li>
<li>set nowrap</li>
<li>&quot;在输入命令时列出匹配项目，也就是截图底部的效果</li>
<li>set wildmenu</li>
<li>&quot;显示光标位置</li>
<li>set ruler</li>
<li>&quot;分割窗口时保持相等的宽/高</li>
<li>set equalalways</li>
<li>&nbsp;</li>
<li>&nbsp;&quot;匹配括号的规则，增加针对html的&lt;&gt;</li>
<li>set matchpairs=(:),{:},[:],&lt;:&gt;</li>
<li>&quot;让退格，空格，上下箭头遇到行首行尾时自动移到下一行（包括insert模式）</li>
<li>set whichwrap=b,s,&lt;,&gt;,[,]</li>
<li>&quot;取消自动备份</li>
<li>set nobackup</li>
<li>&quot;保存关闭文件之前保留一个备份</li>
<li>set writebackup</li>
<li>&nbsp;</li>
<li>&quot;js语法高亮脚本的设置</li>
<li>let g:javascript_enable_domhtmlcss=1</li>
<li>&nbsp;</li>
<li>&quot;设置自定义的&lt;leader&gt;快捷键</li>
<li>let mapleader=&quot;,&quot;</li>
<li>let g:mapleader=&quot;,&quot;</li>
<li>&nbsp;</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>&quot; bufExplorer插件的设置</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>let g:bufExplorerSortBy='mru'</li>
<li>let g:bufExplorerSplitRight=0&nbsp; &nbsp; &nbsp; </li>
<li>let g:bufExplorerSplitVertical=1&nbsp; &nbsp; .</li>
<li>let g:bufExplorerSplitVertSize = 30&nbsp; </li>
<li>let g:bufExplorerUseCurrentWindow=1&nbsp; </li>
<li>autocmd BufWinEnter \[Buf\ List\] setl nonumber</li>
<li>&nbsp;</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>&quot; winManager插件的设置</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>let g:winManagerWindowLayout = &quot;BufExplorer,FileExplorer|TagList&quot;</li>
<li>let g:winManagerWidth = 30</li>
<li>let g:defaultExplorer = 0</li>
<li>nmap &lt;silent&gt; &lt;leader&gt;wm :WMToggle&lt;cr&gt; </li>
<li>&nbsp;</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>&quot; netrw插件的快捷键</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>let g:netrw_winsize = 30</li>
<li>nmap &lt;silent&gt; &lt;leader&gt;fe :Sexplore!&lt;cr&gt;</li>
<li>&nbsp;</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>&quot; NERDTree插件的快捷键</li>
<li>&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;</li>
<li>nmap &lt;silent&gt; &lt;leader&gt;nt :NERDTree&lt;cr&gt;</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li>&quot;把常用的ctrl快捷键映射到苹果键上（只保留cmd+c/cmd+v/cmd+z原有的功能）</li>
<li>map &lt;D-y&gt; &lt;C-y&gt;</li>
<li>map &lt;D-e&gt; &lt;C-e&gt;</li>
<li>map &lt;D-f&gt; &lt;C-f&gt;</li>
<li>map &lt;D-b&gt; &lt;C-b&gt;</li>
<li>map &lt;D-u&gt; &lt;C-u&gt;</li>
<li>map &lt;D-d&gt; &lt;C-d&gt;</li>
<li>map &lt;D-w&gt; &lt;C-w&gt;</li>
<li>map &lt;D-r&gt; &lt;C-r&gt;</li>
<li>map &lt;D-o&gt; &lt;C-o&gt;</li>
<li>map &lt;D-i&gt; &lt;C-i&gt;</li>
<li>map &lt;D-g&gt; &lt;C-g&gt;</li>
<li>map &lt;D-p&gt; &lt;C-p&gt;</li>
<li>map &lt;D-n&gt; &lt;C-n&gt;</li>
<li>map &lt;D-a&gt; &lt;C-a&gt;</li>
<li>cmap &lt;D-d&gt; &lt;C-d&gt;</li></ol></div>
<p>2009.6.7更新：最新的<a href="http://code.google.com/p/yy-vimscript/source/browse/trunk/vimrc" target="_blank">vimrc</a>和其他脚本已经上传到google code的项目仓库里了<br />
<br/><br />
=================步骤二的分割线===================<br />
<br/><br />
然后在个人配置目录里添加语法高亮脚本（~/.vim/syntax/），其中html和css可以直接把vim7自带的脚本复制出来（$VIMRUNTIME/syntax/），js的脚本则推荐用这个：</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=1491" target="_blank">JavaScript syntax : Better JavaScrirpt syntax support<br />
</a></p>
<p>包含更多的关键字以及自动折叠代码的功能，也能在html文件内支持js语法高亮，需要注意的是如果要支持dom方法的关键字，需要在.vimrc里设置一个全局变量javascript_enable_domhtmlcss</p>
<p>我还用了这里的<a href="htmhttp://www.fleiner.com/vim/download.html" target="_blank">html.vim</a>。<br />
<br/><br />
=================步骤三的分割线===================<br />
<br/><br />
接下来就可以对照着syntax脚本，给每个语法组设置颜色，配色脚本需要放到~/.vim/colors/里，然后在.vimrc里用colorscheme命令选定。colors脚本只需要一个，因为syntax脚本末尾都会把自定义的语法组链接到标准语法组，比如：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">HiLink javaScriptDocComment&nbsp; Comment</li></ol></div>
<p>所以只需要定义一套针对标准语法组的配色方案，再通过修改syntax脚本里来调整相应语言的配色。我尝试过针对不同文件类型使用不同的配色方案，发现相当麻烦，需要在切换/打开/关闭缓冲区和窗口的时候都用colorscheme重置配色：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">autocmd BufNewFile,BufRead,BufEnter,WinEnter,FileType *.html,*.htm colorscheme delek</li></ol></div>
<p>而且colorscheme会影响整个窗口（一个vim进程实例），如果在窗口内同时分割显示了几个文件，即使文件类型不同，也会同时改变颜色……</p>
<p>我平时最喜欢TextMate的Blackboard主题（大概是因为里面有橙色罢XD），在Aptana上也仿制过（配置文件：<a href="http://www.limboy.com/conf/eclipse/yytextmate.col" target="_blank">yytextmate.col</a>），这次是直接在vim的slate主题基础上修改出来的，比vim.org上面那个<a href="http://www.vim.org/scripts/script.php?script_id=2280" target="_blank">blackboard.vim</a>要更完善～</p>
<p>我的colors脚本：<a href="http://code.google.com/p/yy-vimscript/source/browse/trunk/colors/yytextmate.vim" target="_blank">yytextmate.vim</a><br />
我调整过的syntax脚本：<a href="http://code.google.com/p/yy-vimscript/source/browse/trunk/syntax/javascript.vim" target="_blank">javascript.vim</a>, <a href="http://code.google.com/p/yy-vimscript/source/browse/trunk/syntax/html.vim" target="_blank">html.vim</a><br />
<br/><br />
=================步骤四的分割线===================<br />
<br/><br />
按照由外向内的顺序，现在该折腾功能了，首先是缩进插件，vim也自带有智能缩进功能，需要开启autoindent和smartindent参数，但是在编辑js代码的时候效果很不好，对于python这种靠缩进活命的语言就更不能忍了，因此至少需要装以下三个插件：</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=1839"  target="_blank">IndentAnything : Write indentations or enhance existing indentations without writing code</a><br />
<a href="http://www.vim.org/scripts/script.php?script_id=1840"  target="_blank">Javascript Indentation : Indentation for Javascript </a><br />
<a href="http://www.vim.org/scripts/script.php?script_id=974"  target="_blank">indent/python.vim : An alternative indentation script for python<br />
</a></p>
<p>第一个放到~/.vim/plugin/里，后两个放在~/.vim/indent/里<br />
<br/><br />
=================步骤五的分割线===================<br />
<br/><br />
<a href='http://www.limboy.com/wp-content/uploads/2009/05/textmate.png' title='textmate.png'><img src='http://www.limboy.com/wp-content/uploads/2009/05/textmate.png' alt='textmate.png' style="float:left;border:0;margin:0 10px 10px 0;" /></a>接下来终于要来实现TextMate最重要的功能了，TextMate之所以被称作地上最贵麦上最强的编辑器，就是因为支持大量可以通过tab或其他快捷键发动的强力Bundles，这些Bundles可以分为两种类型，一种是针对编辑器的内容执行指令（称作command），比如直接执行shell脚本，压缩js代码，对html转义，格式化JSON，编译swf等等，而指令界面是vim的核心，不但可以直接执行shell命令，也可以通过设置键位映射和宏，把复杂的操作绑定成简单的快捷键，因此这类功能原本就是vim的强项。</p>
<p>另一种类型的Bundles主要用来帮助程序员快速开发，通过简短的缩写＋tab键直接生成所需的代码模板（称作snippet），然后依然用tab在模板中需要改动的位置之间跳转，整个过程不需要鼠标定位，非常高效，是一种比大型IDE里常见的&#8221;code hinting&#8221;更实用的智能补全功能。</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=2540"  target="_blank">snipMate : TextMate-style snippets for Vim</a></p>
<p>上面这个非常“新”的插件让vim也具备了同样的功能，而且几乎是跟TextMate完全兼容的移植，比如这是从TextMate里取出的snippet源码：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Gray;">$</span><span style="color: Olive;">{</span><span style="color: Maroon;">1</span><span style="color: Gray;">:</span><span style="color: Blue;">class_name</span><span style="color: Olive;">}</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.$</span><span style="color: Olive;">{</span><span style="color: Maroon;">2</span><span style="color: Gray;">:</span><span style="color: Blue;">method_name</span><span style="color: Olive;">}</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Gray;">$</span><span style="color: Olive;">{</span><span style="color: Maroon;">3</span><span style="color: Gray;">:</span><span style="color: Blue;">first_argument</span><span style="color: Olive;">})</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; $</span><span style="color: Olive;">{</span><span style="color: Maroon;">0</span><span style="color: Gray;">:</span><span style="color: #ffa500;">// body...}</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li></ol></div>
<p>${}标签是代码插入后可以通过tab跳转的“可编辑”位置，其中的序号表示跳转顺序，冒号后的字符是默认内容。这段代码只要在前面加上snippet proto就可以直接放进~/.vim/snippets/javascript.snippets里，通过proto<tab>触发</p>
<p>把常见的程序结构抽象成snippet可以节省很多重复输入，比如这是我定义的一个module模式：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">snippet</span><span style="color: Gray;"> </span><span style="color: Blue;">module</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp;&nbsp; * ${5:Describe what this module does}</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp;&nbsp; * @param {object} ${6:paramName}</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp;&nbsp; */</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;"> $</span><span style="color: Olive;">{</span><span style="color: Maroon;">1</span><span style="color: Gray;">:</span><span style="color: Blue;">classname</span><span style="color: Olive;">}</span><span style="color: Gray;"> = </span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;"> $</span><span style="color: Maroon;">1</span><span style="color: Blue;">Object</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $</span><span style="color: Olive;">{</span><span style="color: Maroon;">2</span><span style="color: Gray;">:</span><span style="color: Blue;">privateMethod1</span><span style="color: Olive;">}</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $</span><span style="color: Olive;">{</span><span style="color: Maroon;">3</span><span style="color: Gray;">:</span><span style="color: Blue;">privateMethod2</span><span style="color: Olive;">}</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">opt</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">publicObj</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">options</span><span style="color: Gray;">: </span><span style="color: Olive;">{}</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $</span><span style="color: Maroon;">2</span><span style="color: Gray;">: $</span><span style="color: Maroon;">1</span><span style="color: Blue;">Object</span><span style="color: Gray;">.$</span><span style="color: Maroon;">2</span><span style="color: Gray;">,</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $</span><span style="color: Maroon;">3</span><span style="color: Gray;">: $</span><span style="color: Maroon;">1</span><span style="color: Blue;">Object</span><span style="color: Gray;">.$</span><span style="color: Maroon;">3</span><span style="color: Gray;">$</span><span style="color: Olive;">{</span><span style="color: Maroon;">4</span><span style="color: Gray;">:,</span><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $.</span><span style="color: Blue;">extend</span><span style="color: Olive;">(</span><span style="color: Blue;">publicObj</span><span style="color: Gray;">.</span><span style="color: Blue;">options</span><span style="color: Gray;">, </span><span style="color: Blue;">opt</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">publicObj</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})()</span><span style="color: Gray;">;</span></li></ol></div>
<p>修改过程中会看到$1,$2,$3自动更新成你键入的名字。</p>
<p>我修改过的完整javascript.snippets：<a href="http://code.google.com/p/yy-vimscript/source/browse/trunk/snippets/javascript.snippets" target="_blank">http://code.google.com/p/yy-vimscript/source/browse/trunk/snippets/javascript.snippets</a></p>
<p>实际上还有一个比较老牌的插件也致力于实现同样的snippet功能：</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=1318" target="_blank">snippetsEmu : An attempt to emulate TextMate&#8217;s snippet expansion</a></p>
<p>但是它支持的模板语法比TextMate差很多，跟上面相同的prototype模板要通过这种形式定义：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline">let st = g:snip_start_tag</li>
<li>let et = g:snip_end_tag</li>
<li>let cd = g:snip_elem_delim</li>
<li>&nbsp;</li>
<li>exec &quot;Snippet proto &quot;.st.&quot;className&quot;.et.&quot;.prototype.&quot;.st.&quot;methodName&quot;.et.&quot; = function(&quot;.st.et.&quot;)&lt;CR&gt;{&lt;CR&gt;&quot;.st.et.&quot;&lt;CR&gt;};&lt;CR&gt;&quot;.st.et</li></ol></div>
<p>缩进容易出错，不支持用序号设定跳转顺序，安装过程也比snipMate繁复，所以被我毫不留恋的淘汰了……</p>
<p>为了实现更广泛的智能补全，还需要一个必装插件：</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=1643" target="_blank">SuperTab continued. : Do all your insert-mode completion with Tab. </a></p>
<p>SuperTab让任意字符都可以通过tab补全，比较取巧的是，它会在缓冲区的上下文中寻找匹配的词来补全，因此不需要附带很庞大的API数据。<br />
<br/><br />
=================步骤六的分割线===================<br />
<br/><br />
下一步需要增强的是文件/项目管理，vim虽然自带一个FileExplorer（直接编辑一个目录时会调用它，比如:e .），还有上面提到过的wildmenu的强力辅助，但是与常见的GUI编辑器和IDE相比，仍然不太直观，因此以下插件值得一装：</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=1658" target="_blank">The NERD tree : A tree explorer plugin for navigating the filesystem</a><br />
我最喜欢的文件导航工具，设置了快捷键,nt直接在侧面打开</p>
<p><a href="http://vim.sourceforge.net/scripts/script.php?script_id=42" target="_blank">bufexplorer : Buffer Explorer / Browser </a><br />
缓冲区导航</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=95" target="_blank">winmanager : A windows style IDE for Vim 6.0</a><br />
把bufexploer和FileExplorer集成在左侧，类似IDE的效果，这个功能不足以让我放弃NERDTree……而且这个插件似乎很久没更新了，连支持Vim7的版本都没有，但是很多人喜欢，所以也推荐一下…… </p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=2607" target="_blank">TaskList.vim : Eclipse like task list</a><br />
实现Eclipse的任务列表</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=69" target="_blank">project.tar.gz : Organize/Navigate projects of files</a><br />
项目导航工具，不过没有Eclipse好用，需要写配置脚本，跟TextMate那种拖来拖去的drawer就更不能比了……<br />
<br/><br />
=================步骤七的分割线===================<br />
<br/><br />
最后推荐的插件都是开发工具：</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=90" target="_blank">vcscommand.vim : CVS/SVN/SVK/git integration plugin</a><br />
SVN/git管理工具，这个是必备罢。没有GUI菜单，不过快捷键也很方便，而且VimDiff是很棒的比较工具</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=2578" target="_blank">javaScriptLint.vim : Displays JavaScript Lint warnings in the quickfix error window</a><br />
看仔细啦～这个不是道格拉斯老爷子的JSLint，那个东西虽然强大（以前没觉得，最近在《代码之美》里看到道格拉斯老爷子描述了“递归下降分析”＋“运算符优先级技术”的动态语言解释器，才知道原来JSLint和JSON parser只是老爷子晒技术的承载体……），但是由于把规范约束在一个JS的安全子集上，适用面不广，设置起来也麻烦，在实际开发工作中未必实用。而<a href="http://javascriptlint.com/" target="_blank">这个Lint</a>就很中规中矩，当然也没自己折腾解释器啦，直接用了Mozilla的js引擎，安装也很方便，提供一个conf文件可以设置警告条件。这个vim插件装上后，保存js文件时都会自动校验代码并显示一个提示信息窗口。</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=39" target="_blank">matchit : extended % matching for HTML, LaTeX, and many other languages</a><br />
vim里的%命令可以在嵌套字符之间跳转（比如括号和引号，我在上面的.vimrc文件里增加了html的<>），这个插件将它的功能扩展到嵌套标签和语句</p>
<p>To be <a href="http://www.limboy.com/2009/06/07/vim-setting-more/" target="_blank">continue</a>&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/05/30/vim-setting/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>土豆招聘Javascript工程师的JD，终于谷出来一个</title>
		<link>http://www.limboy.com/2009/05/16/yet-another-javascript-jd/</link>
		<comments>http://www.limboy.com/2009/05/16/yet-another-javascript-jd/#comments</comments>
		<pubDate>Sat, 16 May 2009 08:34:02 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[土豆网]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/05/16/yet-another-javascript-jd/</guid>
		<description><![CDATA[原本是小麦的文案，被我改的啰嗦了，虽然最近在地铁上读了The Elements of Style，但是文字要写的简洁真的需要足够冷酷，我热血而且贪婪，不忍心漏掉一个信息点，所以简洁与我无缘……这篇JD发到其他地方的时候可能会删减很多，我先自己留一份……另外虽然这份JD仅仅提出了对雇员的要求，没有介绍雇主，但如果你仍然有兴趣，可以直接给我发email。
职位：Javascript开发工程师
简单的说，我们需要的是能“正确”使用Javascript的开发者。不同情况下，“正确”的标准也不尽然相同，作为土豆的javascript工程师，我们希望你大致符合如下的描述：

熟悉JS的语法特性和运行机制，比如词法作用域，闭包，原型链，无类型的OO，并乐于在此基础上钻研和探索用JS开发富客户端和复杂web应用的最佳实践和设计模式（这句话用英文写还蛮好，中文怎么拆哑啊啊啊啊～）
jQuery、YUI、MooTools等JS库，对你来说不仅只是开发工具，更是你学习代码风格、接口设计与程序架构的良师益友，你愿意了解他们，不盲目遵从，也不随意使唤。
重视团队协作，愿意探寻和改进目前还不成熟的前端开发流程，了解各种常用工具，如Firebug，YSlow，JSLint，YUI compressor……
在前端领域，你发布过一些有趣的个人项目，或是参与过开源项目，或是致力于构建自己的库和开发框架，或是作为团队核心成员开发过产品级的web应用。
一些基本前端技能如CSS或PS切图就毋需赘述了。

此外，我们乐见一些更优秀的特质：

持续关注业界的新话题和新技术。你喜欢泡在javaeye，reddit之类技术社区灌水和答疑解惑，或者总是最早读到John Resig，Douglas Crackford，Dion Almae，PPK，Dean Edwards等大牛们的新作品和演讲ppt，或者长年维护自己的博客，分享自己的经验和新实践。
你具备其他语言的开发经验，比如java和php，比如Actionscript3/Flex。这给你带来了更深入的程序设计经验和更高更全面的视角。
对于浏览器中的各种可用资源、特性和差异，你都玩弄于鼓掌之间，你有大量优化和重构方面的经验，致力于编写安全，稳定，简洁而强壮，易于扩展的客户端代码。

以上不是必需的，但如果你完全符合，我们可以考虑将土豆网总部迁至你家附近（哈哈）。
最后，如果你目前还不符合以上的描述，但很渴望做到这些，我们也很愿意为你提供面谈的机会。
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;最后吐槽的分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
我觉得小麦写的最后两句是经典哑，一个字未改～
PS：题图其实是蜘蛛侠里的犀牛人……
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2009/05/rhino-a-5001.jpg' title='rhino-a-5001.jpg'><img src='http://www.limboy.com/wp-content/uploads/2009/05/rhino-a-5001.jpg' alt='rhino-a-5001.jpg' style="width:250px;float:left;margin:0 10px 10px 0;" /></a>原本是<a href="http://www.mikkolee.com/" target="_blank">小麦</a>的文案，被我改的啰嗦了，虽然最近在地铁上读了<a href="http://www.douban.com/subject/1433835/">The Elements of Style</a>，但是文字要写的简洁真的需要足够冷酷，我热血而且贪婪，不忍心漏掉一个信息点，所以简洁与我无缘……这篇JD发到其他地方的时候可能会删减很多，我先自己留一份……另外虽然这份JD仅仅提出了对雇员的要求，没有介绍雇主，但如果你仍然有兴趣，可以直接给我发email。</p>
<p><strong>职位：Javascript开发工程师</strong></p>
<p>简单的说，我们需要的是能“正确”使用Javascript的开发者。不同情况下，“正确”的标准也不尽然相同，作为土豆的javascript工程师，我们希望你大致符合如下的描述：<span id="more-228"></span></p>
<ul>
<li>熟悉JS的语法特性和运行机制，比如词法作用域，闭包，原型链，无类型的OO，并乐于在此基础上钻研和探索用JS开发富客户端和复杂web应用的最佳实践和设计模式（<em>这句话用英文写还蛮好，中文怎么拆哑啊啊啊啊～</em>）</li>
<li>jQuery、YUI、MooTools等JS库，对你来说不仅只是开发工具，更是你学习代码风格、接口设计与程序架构的良师益友，你愿意了解他们，不盲目遵从，也不随意使唤。</li>
<li>重视团队协作，愿意探寻和改进目前还不成熟的前端开发流程，了解各种常用工具，如Firebug，YSlow，JSLint，YUI compressor……</li>
<li>在前端领域，你发布过一些有趣的个人项目，或是参与过开源项目，或是致力于构建自己的库和开发框架，或是作为团队核心成员开发过产品级的web应用。</li>
<li>一些基本前端技能如CSS或PS切图就毋需赘述了。</li>
</ul>
<p>此外，我们乐见一些更优秀的特质：</p>
<ul>
<li>持续关注业界的新话题和新技术。你喜欢泡在javaeye，reddit之类技术社区灌水和答疑解惑，或者总是最早读到John Resig，Douglas Crackford，Dion Almae，PPK，Dean Edwards等大牛们的新作品和演讲ppt，或者长年维护自己的博客，分享自己的经验和新实践。</li>
<li>你具备其他语言的开发经验，比如java和php，比如Actionscript3/Flex。这给你带来了更深入的程序设计经验和更高更全面的视角。</li>
<li>对于浏览器中的各种可用资源、特性和差异，你都玩弄于鼓掌之间，你有大量优化和重构方面的经验，致力于编写安全，稳定，简洁而强壮，易于扩展的客户端代码。</li>
</ul>
<p>以上不是必需的，但如果你完全符合，我们可以考虑将土豆网总部迁至你家附近（哈哈）。</p>
<p>最后，如果你目前还不符合以上的描述，但很渴望做到这些，我们也很愿意为你提供面谈的机会。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;最后吐槽的分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>我觉得小麦写的最后两句是经典哑，一个字未改～</p>
<p>PS：题图其实是蜘蛛侠里的犀牛人……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/05/16/yet-another-javascript-jd/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>写javascript是否要“预留退路”</title>
		<link>http://www.limboy.com/2009/01/20/is_javascript_need_degradation/</link>
		<comments>http://www.limboy.com/2009/01/20/is_javascript_need_degradation/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 08:31:36 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Blogger]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[web服务/应用]]></category>
		<category><![CDATA[用户体验]]></category>
		<category><![CDATA[纯水]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/01/20/is_javascript_need_degradation/</guid>
		<description><![CDATA[早上收到一封邮件，问的正好是我一直如哽在喉的事情：
对于web开发中的预留退路问题，我一直犹豫不决。在安全方面，自然是不能完全相信JavaScript，这点是确定的。但在用户体验方面，是否真的需要处处&#8221;预留退路&#8221;，照顾那些不支持JS或者对JS支持不好的用户吗？而UED工程师们又一直在说，不&#8221;预留退路&#8221;会惹恼数量不少的用户，但却从没有人提起具体会是多少用户、多少比例。不知道YY大神手里有这方面的数据吗？记得YY您在建立Limbo混沌海的时候，就选择了&#8221;不预留退路&#8221;的方式，不知当初又是出于什么原因这样考虑的呢？非常想听听您对&#8221;预留退路&#8221;问题的看法，期待您的回信。

这种设计观念，或者说原则，不管它叫什么名字，比如“预留退路”/“平稳退化”（Graceful Degradation），“渐进增强”（Progressive Enhancement），“不唐突的javascript”（Unobtrusive JavaScript）……从UE的角度来说是非常重要的，它的重要性不仅仅来自“有多少比例的用户不开启javascript支持”，而是因为如今访问web的方式正在变的越来越丰富多样，平板电脑（Tablet PC），上网本（netbook），掌上电脑（UMPC/MID），手机，iphone/ipod touch，这些平台有完全不同的性能，屏幕尺寸，浏览器，和操作方式，它们对javascript的支持也可能不一致（比如我以前抱怨过iphone的差别）。很多“严肃”的网站还需要考虑到“可访问性”（Accessibility），要保证能支持屏幕阅读器之类的设备，让那些有视觉缺陷的用户也可以无障碍的使用。此外还有语义网方面的要求，随着web2.0带来的海量信息，互联网也在向一台超级计算机的方向发展，需要靠网络本身去处理网络上的信息，而不是靠人的肉眼去一张网页一张网页的识别，现在的网页不仅仅是供人阅读，同样也需要面向机器，所以不能因为javascript的使用而影响到内容，让机器无法抓取和识别。
不过，以上这些观念有两方面的局限性：

第一，它们仅仅适用于传统的，“文档”式的网页，互联网的原始形态，只是内容的组织形式和传播手段，对于多数网页来说，内容才是根本，JS只是锦上添花，或者说是调料，最重要的是保证内容的完整语义，可访问性，以及适应过去/现在/未来的多种平台的能力。但是，除了“文档”类型的网页，现在也开始兴起大量的&#8221;web应用&#8221;，它们是在线的服务，也是在线的软件，对它们来说，浏览器是一个容器，网页是一种界面呈现方式，数据是异步获取的，频繁变化的，而且是细粒度的（比如并非一篇完整的文章，而是一若干来自数据库的字段），虽然同样以内容为中心，但是在这个语境里，“内容”是指纯粹的数据，而并非整块整块的HTML，一旦缺少了界面的交互功能，缺少了JS程序的支持，数据根本就无法呈现，也就根本不具备访问这些应用的条件，对于这种类型的网页来说，“预留退路”并非是不可侵犯的信条。
更多情况下，网页是复合的，会同时包含文档和软件应用的特点，于是就应该有选择的采纳那些适用于自己的原则，比如把JS和CSS与内容有效的分离，兼容多种平台，保证核心内容能被搜索引擎抓取，等等。
有一个很好的例子是土豆网的播放页，这是在土豆网全站当中，最重要同时也是web应用特征所占比例最大的页面之一，javascript和flashplayer对它来说是必不可少的基础运行环境，所以你可以看到它的html设计跟其他页面有很大差别：

script标签出现在html顶部——在其他网页里，我们习惯把css放在顶部，js放在底部，让页面先呈现，之后再附加行为，但是在播放页面里，播放器是最重要的内容，播放器加载的速度是最关键的用户体验。
HTML里会包含JS代码——只有一处，就是TUI.player.load，理由同样是为了保证播放器加载速度这个核心用户体验，不得不祭出document.write这种“非常不提倡”的必杀技来写入flash元素
有大量内容通过AJAX获取——比如评论，还有侧栏里的某些模块。因为它们是分离的数据，并非主要内容
没有使用正常的流式布局——player和toolbar都是脱离文档的独立区域，采用绝对定位
侧栏上的视频截图并没有把原始文件地址放在src属性里——延迟加载，如果不拖动滚动条，很多图片就不会无意义的下载

但是在很多方面同样也要做到Unobtrusive：

对于核心内容，比如视频信息，作者信息，都是遵循文档式网页的设计原则，对搜索引擎友好
在豆单播放页里，播放器下面的界面列表虽然是一个界面元素，但是也应该包含在文档的语义中，所以采用html的UL/LI来实现


第二个局限性是：这些原则早晚会过时。以前WaSP成员们千辛万苦推广这些观念的时候，互联网上到处都是惨不忍睹的网页，建立标准和规范，进行观念的革新，这些需求胜过了对技术的应用，而现在web标准早已普及，web应用需要进一步发展。以前Douglas Crockford，PPK在传道的时候，国外的网站还必须支持ie5.5甚至5.0之类的浏览器，恶劣的环境让web设计者和开发者们必须自我约束JS的使用，避免形成门槛。而现在，ie6在国外的占有率已经开始低于firefox（20%），很多网站已经开始放弃对ie6的支持，google和yahoo也在引导用户替换ie6。刚才我提到过，通过各种移动设备访问web的用户正在迅速增多，而这些设备对JS的支持不一致，但是这就像桌面电脑上的发展过程一样，同样是一个暂时现象，随着webkit变成iphone，android，palm pre这些新平台的统一标准，Mozilla也在积极把XUL技术应用到移动平台，环境的变化其实比桌面电脑要快的多。
我认为Graceful Degradation，Progressive Enhancement，Unobtrusive JavaScript这类东西都不适合过度的鼓吹，它们只是基础概念，是在特定时期特定环境中形成的经验和指导，而不应该是束缚前端开发人员和产品设计人员的教条，实际上，这些保守的观念来自技术的局限，而技术的局限不是我们逃避使用技术的理由，相反，我们可以仍然使用技术来打破这些局限，我们需要的是像ie7.js，excanvas.js，jquery.js这样的解决方案，而不是在开发中畏首畏尾，把每个前端开发者都教唆成原教旨主义者（上次我们公司的小麦对我说：前端开发都有这种倾向……我要说这是历史遗留的伤痕，将在世代中流传下去……）

================吐槽结束的分割线================

最后回复两个邮件里的问题……
关于用户的统计数据，土豆网是有的，可以想象由于多数用户比较大众和小白，IE6的比例相当高，比较冏的是，腾讯TT的比例也很高，等同于Firefox，我必须说它那种跟QQ绑定在一起，经常无意中启动，启动之后就设置为默认浏览器的套路，确实很强大……在普通用户当中，“默认”是强大的力量，默认的通常就是最熟悉的，最熟悉的就是最好的……不过，统计数据有时并不能真正反映出用户数量，比如Opera用户在你的统计数据里只占到0.01%，你就要思考一下究竟是Opera用户确实只有这么多，还是你的网站对Opera支持太差，导致人家都不来……
关于我的blog……其实我很早就计划重做这个blog了，现在的版本是一年半前的，从技术上来说很幼稚，我都懒得优化和修补了……但是，即使重做，我仍然不会把别人的“用户体验”放在第一位，就像侧栏里说明的那样：“优先满足个人喜好”。blog有很多类型，有的是个人媒体，有的是文集，有的是日记，有的是个性化空间，而我想要的blog是“个人信息聚合”，除了满足阅读的需求，必然还要包含大量个性化内容，也就是说，用户首先是我，其次才是读者和我的好友，而对于阅读者来说，浏览方式不止一种，比如我自己就更习惯用google reader来阅读blog，如果用户愿意选择网页形式来访问，就会被强加很多个性化内容，桀桀桀，喜欢的继续看，不喜欢的关掉页面离开，这也算双向选择罢……
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2009/01/cloudbook.jpg' title='cloudbook.jpg'><img src='http://www.limboy.com/wp-content/uploads/2009/01/cloudbook.jpg' alt='cloudbook.jpg' style="border:0;float:left;margin:0 5px 5px 0;width:200px;" /></a>早上收到一封邮件，问的正好是我一直如哽在喉的事情：</p>
<p><em style="display:block">对于web开发中的预留退路问题，我一直犹豫不决。在安全方面，自然是不能完全相信JavaScript，这点是确定的。但在用户体验方面，是否真的需要处处&#8221;预留退路&#8221;，照顾那些不支持JS或者对JS支持不好的用户吗？而UED工程师们又一直在说，不&#8221;预留退路&#8221;会惹恼数量不少的用户，但却从没有人提起具体会是多少用户、多少比例。不知道YY大神手里有这方面的数据吗？记得YY您在建立Limbo混沌海的时候，就选择了&#8221;不预留退路&#8221;的方式，不知当初又是出于什么原因这样考虑的呢？非常想听听您对&#8221;预留退路&#8221;问题的看法，期待您的回信。</em><br />
<span id="more-216"></span><br />
这种设计观念，或者说原则，不管它叫什么名字，比如“预留退路”/“平稳退化”（Graceful Degradation），“渐进增强”（Progressive Enhancement），“不唐突的javascript”（Unobtrusive JavaScript）……从UE的角度来说是非常重要的，它的重要性不仅仅来自“有多少比例的用户不开启javascript支持”，而是因为如今访问web的方式正在变的越来越丰富多样，平板电脑（Tablet PC），上网本（netbook），掌上电脑（UMPC/MID），手机，iphone/ipod touch，这些平台有完全不同的性能，屏幕尺寸，浏览器，和操作方式，它们对javascript的支持也可能不一致（比如我以前抱怨过<a target="_blank" href="http://www.limboy.com/2008/03/08/iphone-app-develop/">iphone的差别</a>）。很多“严肃”的网站还需要考虑到<a target="_blank" href="http://www.junchenwu.com/WAI/wai-pageauth.html">“可访问性”（Accessibility）</a>，要保证能支持屏幕阅读器之类的设备，让那些有视觉缺陷的用户也可以无障碍的使用。此外还有语义网方面的要求，随着web2.0带来的海量信息，互联网也在向一台超级计算机的方向发展，需要靠网络本身去处理网络上的信息，而不是靠人的肉眼去一张网页一张网页的识别，现在的网页不仅仅是供人阅读，同样也需要面向机器，所以不能因为javascript的使用而影响到内容，让机器无法抓取和识别。</p>
<p>不过，以上这些观念有两方面的局限性：<br />
<br/></p>
<p>第一，它们仅仅适用于传统的，“文档”式的网页，互联网的原始形态，只是内容的组织形式和传播手段，对于多数网页来说，内容才是根本，JS只是锦上添花，或者说是调料，最重要的是保证内容的完整语义，可访问性，以及适应过去/现在/未来的多种平台的能力。但是，除了“文档”类型的网页，现在也开始兴起大量的&#8221;web应用&#8221;，它们是在线的服务，也是在线的软件，对它们来说，浏览器是一个容器，网页是一种界面呈现方式，数据是异步获取的，频繁变化的，而且是细粒度的（比如并非一篇完整的文章，而是一若干来自数据库的字段），虽然同样以内容为中心，但是在这个语境里，“内容”是指纯粹的数据，而并非整块整块的HTML，一旦缺少了界面的交互功能，缺少了JS程序的支持，数据根本就无法呈现，也就根本不具备访问这些应用的条件，对于这种类型的网页来说，“预留退路”并非是不可侵犯的信条。</p>
<p>更多情况下，网页是复合的，会同时包含文档和软件应用的特点，于是就应该有选择的采纳那些适用于自己的原则，比如把JS和CSS与内容有效的分离，兼容多种平台，保证核心内容能被搜索引擎抓取，等等。</p>
<p>有一个很好的例子是<a target="_blank" href="http://www.tudou.com/playlist/playindex.do?lid=4888295">土豆网的播放页</a>，这是在土豆网全站当中，最重要同时也是web应用特征所占比例最大的页面之一，javascript和flashplayer对它来说是必不可少的基础运行环境，所以你可以看到它的html设计跟其他页面有很大差别：</p>
<ul>
<li>script标签出现在html顶部——在其他网页里，我们习惯<a target="_blank" href="http://developer.yahoo.com/performance/rules.html#js_bottom">把css放在顶部，js放在底部</a>，让页面先呈现，之后再附加行为，但是在播放页面里，播放器是最重要的内容，播放器加载的速度是最关键的用户体验。</li>
<li>HTML里会包含JS代码——只有一处，就是TUI.player.load，理由同样是为了保证播放器加载速度这个核心用户体验，不得不祭出document.write这种“非常不提倡”的必杀技来写入flash元素</li>
<li>有大量内容通过AJAX获取——比如评论，还有侧栏里的某些模块。因为它们是分离的数据，并非主要内容</li>
<li>没有使用正常的流式布局——player和toolbar都是脱离文档的独立区域，采用绝对定位</li>
<li>侧栏上的视频截图并没有把原始文件地址放在src属性里——延迟加载，如果不拖动滚动条，很多图片就不会无意义的下载</li>
</ul>
<p>但是在很多方面同样也要做到Unobtrusive：</p>
<ul>
<li>对于核心内容，比如视频信息，作者信息，都是遵循文档式网页的设计原则，对搜索引擎友好</li>
<li>在豆单播放页里，播放器下面的界面列表虽然是一个界面元素，但是也应该包含在文档的语义中，所以采用html的UL/LI来实现</li>
</ul>
<p><br/></p>
<p>第二个局限性是：这些原则早晚会过时。以前<a target="_blank" href="http://www.webstandards.org/">WaSP</a>成员们千辛万苦推广这些观念的时候，互联网上到处都是惨不忍睹的网页，建立标准和规范，进行观念的革新，这些需求胜过了对技术的应用，而现在web标准早已普及，web应用需要进一步发展。以前Douglas Crockford，PPK在传道的时候，国外的网站还必须支持ie5.5甚至5.0之类的浏览器，恶劣的环境让web设计者和开发者们必须自我约束JS的使用，避免形成门槛。而现在，ie6在国外的占有率已经开始<a target="_blank" href="http://ajaxian.com/archives/i-wont-support-ie-6-in-2009">低于firefox（20%）</a>，很多网站已经开始<a href="http://www.infoq.com/cn/news/2008/07/ie6_on_its_way_out">放弃对ie6的支持</a>，google和yahoo也在引导用户替换ie6。刚才我提到过，通过各种移动设备访问web的用户正在迅速增多，而这些设备对JS的支持不一致，但是这就像桌面电脑上的发展过程一样，同样是一个暂时现象，随着webkit变成iphone，android，palm pre这些新平台的统一标准，Mozilla也在积极<a target="_blank" href="http://arstechnica.com/news.ars/post/20081224-mozilla-releases-second-alpha-of-fennec-mobile-browser.html">把XUL技术应用到移动平台</a>，环境的变化其实比桌面电脑要快的多。</p>
<p>我认为Graceful Degradation，Progressive Enhancement，Unobtrusive JavaScript这类东西都不适合过度的鼓吹，它们只是基础概念，是在特定时期特定环境中形成的经验和指导，而不应该是束缚前端开发人员和产品设计人员的教条，实际上，这些保守的观念来自技术的局限，而技术的局限不是我们逃避使用技术的理由，相反，我们可以仍然使用技术来打破这些局限，我们需要的是像<a target="_blank" href="http://code.google.com/p/ie7-js/">ie7.js</a>，<a target="_blank" href="http://excanvas.sourceforge.net/">excanvas.js</a>，jquery.js这样的解决方案，而不是在开发中畏首畏尾，把每个前端开发者都教唆成原教旨主义者（上次我们公司的小麦对我说：前端开发都有这种倾向……我要说这是历史遗留的伤痕，将在世代中流传下去……）<br />
<br/><br />
================吐槽结束的分割线================<br />
<br/><br />
最后回复两个邮件里的问题……</p>
<p>关于用户的统计数据，土豆网是有的，可以想象由于多数用户比较大众和小白，IE6的比例相当高，比较冏的是，腾讯TT的比例也很高，等同于Firefox，我必须说它那种跟QQ绑定在一起，经常无意中启动，启动之后就设置为默认浏览器的套路，确实很强大……在普通用户当中，“默认”是强大的力量，默认的通常就是最熟悉的，<a target="_blank" href="http://www.ruanyifeng.com/blog/2009/01/font_smoothing_anti-aliasing_and_sub-pixel_rendering.html">最熟悉的就是最好的</a>……不过，统计数据有时并不能真正反映出用户数量，比如Opera用户在你的统计数据里只占到0.01%，你就要思考一下究竟是Opera用户确实只有这么多，还是你的网站对Opera支持太差，导致人家都不来……</p>
<p>关于我的blog……其实我很早就计划重做这个blog了，现在的版本是一年半前的，从技术上来说很幼稚，我都懒得优化和修补了……但是，即使重做，我仍然不会把别人的“用户体验”放在第一位，就像侧栏里说明的那样：“优先满足个人喜好”。blog有很多类型，有的是个人媒体，有的是文集，有的是日记，有的是个性化空间，而我想要的blog是“个人信息聚合”，除了满足阅读的需求，必然还要包含大量个性化内容，也就是说，用户首先是我，其次才是读者和我的好友，而对于阅读者来说，浏览方式不止一种，比如我自己就更习惯用google reader来阅读blog，如果用户愿意选择网页形式来访问，就会被强加很多个性化内容，桀桀桀，喜欢的继续看，不喜欢的关掉页面离开，这也算双向选择罢……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/01/20/is_javascript_need_degradation/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>jQuery1.3和里程碑式的新选择器引擎</title>
		<link>http://www.limboy.com/2009/01/15/jquery13_new_selector_engine_sizzle/</link>
		<comments>http://www.limboy.com/2009/01/15/jquery13_new_selector_engine_sizzle/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 19:27:48 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[代码]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/01/15/jquery13_new_selector_engine_sizzle/</guid>
		<description><![CDATA[John Resig老爷在twitter上宣布jQuery1.3正式发布，直接把2加到3反映了这个版本的重要性不同以往，除了重写很多重要方法——比如offset（获取页面上的各种尺寸和位置数据），创建和插入DOM节点（比如append, before之类，这些方法是JQuery以前速度上的瓶颈之一，我就完全不用它们，但是现在速度提高了6倍）——最重要的改变是启用了全新的Sizzle引擎来实现CSS选择器。
从“JQuery”这个名字就能看出，用CSS/XML选择器查询页面元素，是这个javascript库赖以起家的绝活，最早可以追溯到Dean Edwards的cssQuery，和Simon Willison的getElementsBySelector，但是在那个上古时代（史料记载中无正式名称，我们可以称之为“Age of the First Bubble”，或者“DHTML Era”，虽然也有学者认为希腊神话中描述的黑铁时代（Iron Age）就是指那段时间……dojo创始人Alex Russell，以及prototype创始人Sam Stephenson，都是来自那个时代地淫～），面对恶劣的浏览器环境和粗糙的web应用，这些选择器的实现只能被当作geek的实验，没有应用市场。而到了05年，世界已经进入web2.0和ajax的新纪元，84年出生的天才少年John Resig（555跟我同年~>_]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2009/01/15/jquery13_new_selector_engine_sizzle/rockstarjpg/' rel='attachment wp-att-211' title='rockstar.jpg'><img src='http://www.limboy.com/wp-content/uploads/2009/01/rockstar.jpg' alt='rockstar.jpg' style="border:0;float:left;margin:0 10px 0 0;" /></a>John Resig老爷在<a href="http://twitter.com/jeresig/status/1118348417" target="_blank">twitter</a>上宣布jQuery1.3正式发布，直接把2加到3反映了这个版本的重要性不同以往，除了重写很多重要方法——比如offset（获取页面上的各种尺寸和位置数据），创建和插入DOM节点（比如append, before之类，这些方法是JQuery以前速度上的瓶颈之一，我就完全不用它们，但是现在速度提高了6倍）——最重要的改变是启用了全新的Sizzle引擎来实现CSS选择器。</p>
<p>从“JQuery”这个名字就能看出，用CSS/XML选择器查询页面元素，是这个javascript库赖以起家的绝活，最早可以追溯到Dean Edwards的<a target="_blank" href="http://dean.edwards.name/my/cssQuery/">cssQuery</a>，和Simon Willison的<a target="_blank" href="http://simonwillison.net/2003/Mar/25/getElementsBySelector/">getElementsBySelector</a>，但是在那个上古时代（史料记载中无正式名称，我们可以称之为“Age of the First Bubble”，或者“DHTML Era”，虽然也有学者认为希腊神话中描述的黑铁时代（Iron Age）就是指那段时间……dojo创始人<a target="_blank" href="http://alex.dojotoolkit.org/">Alex Russell</a>，以及prototype创始人<a target="_blank" href="http://conio.net/">Sam Stephenson</a>，都是来自那个时代地淫～），<span id="more-210"></span>面对恶劣的浏览器环境和粗糙的web应用，这些选择器的实现只能被当作geek的实验，没有应用市场。而到了05年，世界已经进入web2.0和ajax的新纪元，84年出生的天才少年John Resig（555跟我同年~>_<~）在先行者的启发下（必须承认D Edwards老爷“启发”了很多人……自己的作品却没机会进入主流）开始探索选择器技术，一年后的1月15日（没错今天是jQuery三周年生日）就在<a target="_blank" href="http://ejohn.org/blog/barcampnyc-wrap-up/">纽约的Barcamp</a>上正式发布了第一版的JQuery，迅速红遍全球，流行程度堪比摇滚巨星（我就很喜欢JQuery去年发布1.2.6时搞得那个<a target="_blank" href="http://farm4.static.flickr.com/3026/2809148861_45a9c46390_o.png">摇滚主题的主页</a>哑！）<img src='http://www.limboy.com/wp-content/uploads/2009/01/jquery-logo.gif' alt='jquery-logo.gif' style="border:0;margin:0;float:right;" /></p>
<p>在JQuery的影响下，选择器逐渐变成了javascript开发的主流需求，其他的库不进则死，都匆匆引入选择器，比如dojo.query，YAHOO.util.Selector.query，$$……甚至各大浏览器厂商也开始实现W3C最新的<a target="_blank" href="http://www.w3.org/TR/selectors-api/">Selectors API标准</a>（包括Safari3.1、Firefox3.1、IE8 beta，居然连IE也实现了耶！可见这个现象的反常程度……）</p>
<p>但是当选择器的实现变得无处不在五花八门的时候（我以前做的<a target="_blank" href="http://www.limboy.com/2008/05/31/yyopml-release/">JQuery迷你版</a>里也有一个自己实现的选择器-___-b），开发者们又有了新烦恼，他们需要统一的，能平稳迁移/升级的接口，需要最高效的实现，随着W3C Selectors API的实现，统一标准也变得更加重要和紧迫，于是John Resig就像武林盟主一样站出来开发了一个纯粹而高效的选择器引擎——<a target="_blank" href="http://github.com/jeresig/sizzle/">Sizzle</a>，并主动贡献给<a target="_blank" href="http://ajaxian.com/archives/a-great-example-of-sharing-sizzle-engine-in-dojo-foundation">prototype, dojo, Mochkit等各大门派</a>，jQuery1.3是第一个采用Sizzle的正式产品，可以看到速度有<a target="_blank" href="http://docs.jquery.com/Release:jQuery_1.3#Performance">显著的提升</a>，今后的发展非常令人期待。</p>
<p>Sizzle反映了一种新趋势，随着javascript库的逐渐成熟，一些功能开始被分离出来设计成独立维护的引擎/核心。实际上现在的主流库里，有很多代码都互相借鉴，并采纳blogsphere里讨论出的最新最好的实现方法，比如jQuery的DOM Ready方法就可以明显看到这种演进，而那些涉及跨浏览器的实现和bug fix，尤其容易趋向于统一。有机会产生通用引擎的领域，除了css选择器，可以预见的还有2D/3D绘图引擎（封装canvas,VML或SVG），模板引擎，对象映射，文本解析，动画，运动和定位相关的计算，还有一些基础代码，比如迭代器。</p>
<p>不过关于选择器，还有一点必须指出的是，无论选择器发展的多么高效，即使有一天能完全当作native实现来对待，也不能过度的依赖它来完成任务，满足于写一些脚本式的代码，而忽视javascript语言本身的算法，数据结构和模式。这个道理其实就类似php和mysql的关系，php作为服务器端专业的web开发语言，有大量开发工作是围绕着数据来进行，而强大的mysql已经实现很多针对数据查询的算法和逻辑，加上php本身与其说是一门语言，不如说是工具包，导致很多初心的php程序员简单的依赖于mysql，编程能力普遍不高，进而损害到了php程序员的平均工资……</p>
<p>从这个角度上来讲，javascript跟php非常相像，虽然javascript本身是一门强悍而集大成的语言（记得上次去帝都参加SD2C时，<a target="_blank" href="http://www.sd2china2008.com/track2#a28">天际网的CTO郭应寿</a>说“喜欢技术的人不可能不喜欢javascript”），但是多数时候都被限制在浏览器的sandbox里，曾经一度沦为真正的“脚本语言”，多亏浏览器后来施舍了DOM和xhr，才让javascript有了用武之地，所以js在很大程度上也是围绕着DOM在编程，DOM是前端最重要的数据结构，有了强大的选择器工具，很多需求只要反复调用选择器，写几串脚本式的代码就能实现，如果满足于这种开发方式，不站在更高的角度去设计和构建应用，对于自己和自己的工作都可以说是非常危险的。</p>
<p>另外，设计良好的html，重要性相当于后端的数据库设计，可以让选择器的使用变得更高效，并直接影响js的设计模式。我在一些项目中非常喜欢这样的理念：在保证语义和简洁的前提下，让HTML成为一种配置文件，当需求有变化，或是在一些可复用的场合，只需要简单的编写html，就能自动实现相应的程序逻辑。对于选择器的使用，还存在另一种截然相反的设计方式：在有些情况下，需要让javascript和html尽可能的解耦合，让同样的代码可以适应灵活变化的html结构，并尽可能减少dom操作，具体的例子会在下篇文章中给出。</p>
<p>其实本来今天最想写的是jQuery1.3中新增的Live Events，因为土豆网全局js里正好有一个自己实现的方法$.fn.eventProxy，两者基于同样的设计模式，明天有空的时候再写算了，这篇就当作向三岁的JQuery致敬。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/01/15/jquery13_new_selector_engine_sizzle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iframe和异步的跨域请求，结合土豆网的实例</title>
		<link>http://www.limboy.com/2008/12/31/iframe-cross-site-request/</link>
		<comments>http://www.limboy.com/2008/12/31/iframe-cross-site-request/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 19:00:46 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[土豆网]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2008/12/31/iframe-cross-site-request/</guid>
		<description><![CDATA[这篇文章将会探讨一下在网页里做异步的跨域请求，以及借助iframe来获取数据的方法。
呃，本来我觉得这个话题没什么好说的了，因为如今好像没有几个web应用能离开这类request，google和facebook用iframe来做comet的时候也基本上把能hack的都hack遍了，所以我估计开发者社区里应该早就形成所谓的&#8221;最佳实践&#8221;（best practices）了罢。不过最近看到有一些关注前端技术的blog（比如realazy）在讨论相关的话题，发现还是有一些东西值得写下来。

一、借助script的异步跨域请求
先说跨域的问题，首先要指出的是，iframe里的js宿主对象一样也躲不开同源策略（Same Origin Policy），仅仅能解决二级域名的跨域而已，比如www.tudou.com和so.tudou.com，如果要请求某个八杆子打不到一起去的域名下的数据（例如你想搞mashup），建议老老实实的用script标签去请求JSONP罢。关于JSONP要附带说一下的是，jQuery对JSONP请求的封装方式很值得提倡：
$.getJSON(url, params + &#34;&#38;jsoncallback=?&#34;, function(json){
&#160; &#160; /* do something */
});
用jsoncallback作为服务器端支持的标准jsonp参数，而每次执行这个方法都会用时间戳生成一个唯一的全局函数名，替换这个“?”，这个细节被封装到黑盒里，使用者不必了解，可以像普通的ajax请求一样，用匿名的回调函数作为最末尾的参数（这是jquery强调的风格），这种语法糖（syntactic sugar）的作用绝对不仅仅是让前端开发人员可以偷懒而已，对代码的可读性，兼容性和今后的维护都有好处。（我经常要向服务器端的开发人员解释这个道理，否则他们才不给你支持什么jsoncallback参数呢，直接给你返回一个“yy({……})”就算完工……囧）
二、利用前沿技术的跨域方法
当然了，我们还可以走一些目前来看比较野的路子来实现跨域，比如在页面里嵌入一个不到1K的swf，借助flashplayer向部署了crossdomain.xml的服务器请求数据，再用actionscript里的ExternalInterface类把数据还给javascript（我觉得这种方法忒有调用dll的感觉～大心）。
我们还可以指望ie8里支持的XDomainRequestAllowed，和firefox3.1支持的Access Control，甚至传说中的HTML5 socket……噢喔喔，多么甜美的梦……/掐一把脸蛋
三、用iframe直接发送跨域请求
跟script标签一样，iframe也可以用来替代ajax，而且在修改document.domain之后（比如上面提到的两个域名，可以设置document.domain = &#8220;tudou.com&#8221;），还可以解决部分跨域问题。
通过iframe请求数据的方法，最直接的莫过于在页面里动态的嵌入一个iframe标签，用它的src属性直接请求包含数据的网页，然后利用那个网页里的js把数据传给父页面，比如：
&#60;iframe id=&#34;crossdomain&#34; width=&#34;0&#34; height=&#34;0&#34; style=&#34;visibility:hidden;&#34; src=&#34;http://yoursite.com/request_url/&#34; &#62;&#60;/iframe&#62;
这种方法耦合的太紧，非常不推荐。你请求的URI代表一个资源，应该是单纯的数据，它会作为xml，json，js代码还是html来处理，这个并不重要，不应该把你的程序逻辑跟数据混杂到一起，数据也不应该因为跨域或不跨域，用iframe，script还是ajax来请求就变成完全不同的东西。
有人会说：为了让数据能够被JS处理，返回的内容难免有差异。——但是小的差异可以通过合理的封装隐藏起来，比如JQuery的getJSON方法
有人会说：请求的URI是一个动态页面，同样可以在URI里支持类似jsoncallback的参数，生成一个script标签和其中的JS代码，把数据“包裹”在JS里，比如请求“http://yoursite.com/request_url/?callback=cb1304344”，返回：
&#60;script type=&#34;text/javascript&#34;&#62;
document.domain=&#34;tudou.com&#34;;
top.cb1304344({ /* 数据 */ });
&#60;/script&#62;
——首先，很多情况下你请求到的不会是动态页面，在这个到处都强调高负载的web世界里，你拿到的经常是squid之类的代理程序返回的缓存。其次，如果你请求的是HTML格式的文本，为了能作为JS代码来执行，服务器端必须对这段文本做转义和清理工作，而且安全性还不一定能保证（因为HTML里经常包含很多来自UGC的内容），如果你请求的是JSON格式的数据……那何必用iframe咧……直接嵌script罢……
四、用iframe直接请求数据的最佳实践
我推荐在上述方法的基础上做改良，首先在服务器端，直接返回数据本身，并且把数据“包裹”在一个textarea标签里，比如：
&#60;textarea&#62;&#60;div&#62;&#60;p&#62;yyyyy&#60;/p&#62;&#60;/div&#62;&#60;/textarea&#62;
textarea的优点是可以支持任何格式的内容，而且这些内容不会在iframe子页面里解析（比如创建DOM树，执行JS），接下来前端要做的，只是在父页面里获取到子页面的DOM，把textarea的内容取出来（注意不能取innerHTML而要取value）。
这里存在一个判断iframe是否加载完成的问题，解决方法之一是在iframe标签上写onload事件，不过这样就需要显式的调用一个函数。
方法二如下：
(function(){
try{
&#160; &#160; callback(document.getElementById('crossdomain').contentWindow.document.body.getElementsByTagName(&#34;TEXTAREA&#34;)[0].value);
}catch(e){
&#160; &#160; setTimeout(arguments.callee,0);
&#160; &#160; return;
}&#160; &#160; 
})();
最后我们可以封装出这样一个方法：
window.TUI = window.$ = {};
/**
 * @public 通过iframe异步请求数据
 * @param {string}&#160; url是请求的地址
 * @param {function}&#160; cb是处理返回数据的回调函数
 */
TUI.getIframeData = function(url, [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2008/12/tudou_frame.jpg' title='tudou_frame.jpg'><img style="float:left;width:200px;margin:0 10px 10px 0;" src='http://www.limboy.com/wp-content/uploads/2008/12/tudou_frame.jpg' alt='tudou_frame.jpg' /></a>这篇文章将会探讨一下在网页里做异步的跨域请求，以及借助iframe来获取数据的方法。</p>
<p>呃，本来我觉得这个话题没什么好说的了，因为如今好像没有几个web应用能离开这类request，google和facebook用iframe来做comet的时候也基本上把能hack的都hack遍了，所以我估计开发者社区里应该早就形成所谓的&#8221;最佳实践&#8221;（best practices）了罢。不过最近看到有一些关注前端技术的blog（比如<a target="_blank" href="http://realazy.org/blog/2008/11/30/benifit-of-fecthing-page-via-iframe/">realazy</a>）在讨论相关的话题，发现还是有一些东西值得写下来。<span id="more-208"></span></p>
<p><br/></p>
<h3>一、借助script的异步跨域请求</h3>
<p>先说跨域的问题，首先要指出的是，iframe里的js宿主对象一样也躲不开同源策略（Same Origin Policy），仅仅能解决二级域名的跨域而已，比如www.tudou.com和so.tudou.com，如果要请求某个八杆子打不到一起去的域名下的数据（例如你想搞mashup），建议老老实实的用script标签去请求<a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/" target="_blank">JSONP</a>罢。关于JSONP要附带说一下的是，jQuery对JSONP请求的封装方式很值得提倡：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Gray;">$.</span><span style="color: Blue;">getJSON</span><span style="color: Olive;">(</span><span style="color: Blue;">url</span><span style="color: Gray;">, </span><span style="color: Blue;">params</span><span style="color: Gray;"> + </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">&amp;jsoncallback=?</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">json</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">/* do something */</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>用jsoncallback作为服务器端支持的标准jsonp参数，而每次执行这个方法都会用时间戳生成一个唯一的全局函数名，替换这个“?”，这个细节被封装到黑盒里，使用者不必了解，可以像普通的ajax请求一样，用匿名的回调函数作为最末尾的参数（这是jquery强调的风格），这种语法糖（syntactic sugar）的作用绝对不仅仅是让前端开发人员可以偷懒而已，对代码的可读性，兼容性和今后的维护都有好处。（我经常要向服务器端的开发人员解释这个道理，否则他们才不给你支持什么jsoncallback参数呢，直接给你返回一个“yy({……})”就算完工……囧）</p>
<h3>二、利用前沿技术的跨域方法</h3>
<p>当然了，我们还可以走一些目前来看比较野的路子来实现跨域，比如在页面里嵌入一个不到1K的swf，借助flashplayer向部署了crossdomain.xml的服务器请求数据，再用actionscript里的ExternalInterface类把数据还给javascript（我觉得这种方法忒有调用dll的感觉～大心）。</p>
<p>我们还可以指望ie8里支持的<a target="_blank" href="http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=ie8whitepapers&#038;ReleaseId=581">XDomainRequestAllowed</a>，和firefox3.1支持的<a target="_blank" href="http://dev.w3.org/2006/waf/access-control/">Access Control</a>，甚至传说中的<a target="_blank" href="http://www.reddit.com/r/programming/comments/7a3rc/html_5_websocket_is_neither_web_nor_socket/">HTML5 socket</a>……噢喔喔，多么甜美的梦……/掐一把脸蛋</p>
<h3>三、用iframe直接发送跨域请求</h3>
<p>跟script标签一样，iframe也可以用来替代ajax，而且在修改document.domain之后（比如上面提到的两个域名，可以设置document.domain = &#8220;tudou.com&#8221;），还可以解决部分跨域问题。</p>
<p>通过iframe请求数据的方法，最直接的莫过于在页面里动态的嵌入一个iframe标签，用它的src属性直接请求包含数据的网页，然后利用那个网页里的js把数据传给父页面，比如：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">iframe</span><span style="color: Gray;"> </span><span style="color: #00008b;">id</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">crossdomain</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">width</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">0</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">height</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">0</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">style</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">visibility:hidden;</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">src</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">http://yoursite.com/request_url/</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">&gt;&lt;/</span><span style="color: Green;">iframe</span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>这种方法耦合的太紧，非常不推荐。你请求的URI代表一个资源，应该是单纯的数据，它会作为xml，json，js代码还是html来处理，这个并不重要，不应该把你的程序逻辑跟数据混杂到一起，数据也不应该因为跨域或不跨域，用iframe，script还是ajax来请求就变成完全不同的东西。</p>
<p>有人会说：为了让数据能够被JS处理，返回的内容难免有差异。——但是小的差异可以通过合理的封装隐藏起来，比如JQuery的getJSON方法</p>
<p>有人会说：请求的URI是一个动态页面，同样可以在URI里支持类似jsoncallback的参数，生成一个script标签和其中的JS代码，把数据“包裹”在JS里，比如请求“http://yoursite.com/request_url/?callback=cb1304344”，返回：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">script</span><span style="color: Gray;"> </span><span style="color: #00008b;">type</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">text/javascript</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">document.domain=&quot;tudou.com&quot;;</span></li>
<li><span style="color: Gray;">top.cb1304344({ /* 数据 */ });</span></li>
<li><span style="color: Olive;">&lt;/</span><span style="color: Green;">script</span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>——首先，很多情况下你请求到的不会是动态页面，在这个到处都强调高负载的web世界里，你拿到的经常是<a target="_blank" href="http://blog.s135.com/book/squid/">squid</a>之类的代理程序返回的缓存。其次，如果你请求的是HTML格式的文本，为了能作为JS代码来执行，服务器端必须对这段文本做转义和清理工作，而且安全性还不一定能保证（因为HTML里经常包含很多来自UGC的内容），如果你请求的是JSON格式的数据……那何必用iframe咧……直接嵌script罢……</p>
<h3>四、用iframe直接请求数据的最佳实践</h3>
<p>我推荐在上述方法的基础上做改良，首先在服务器端，直接返回数据本身，并且把数据“包裹”在一个textarea标签里，比如：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">textarea</span><span style="color: Olive;">&gt;&lt;</span><span style="color: Green;">div</span><span style="color: Olive;">&gt;&lt;</span><span style="color: Green;">p</span><span style="color: Olive;">&gt;</span><span style="color: Gray;">yyyyy</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">p</span><span style="color: Olive;">&gt;&lt;/</span><span style="color: Green;">div</span><span style="color: Olive;">&gt;&lt;/</span><span style="color: Green;">textarea</span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>textarea的优点是可以支持任何格式的内容，而且这些内容不会在iframe子页面里解析（比如创建DOM树，执行JS），接下来前端要做的，只是在父页面里获取到子页面的DOM，把textarea的内容取出来（注意不能取innerHTML而要取value）。</p>
<p>这里存在一个判断iframe是否加载完成的问题，解决方法之一是在iframe标签上写onload事件，不过这样就需要显式的调用一个函数。</p>
<p>方法二如下：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Green;">try</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">callback</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">getElementById</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">crossdomain</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">contentWindow</span><span style="color: Gray;">.</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">body</span><span style="color: Gray;">.</span><span style="color: Blue;">getElementsByTagName</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">TEXTAREA</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)[</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">.</span><span style="color: Blue;">value</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Green;">catch</span><span style="color: Olive;">(</span><span style="color: Blue;">e</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">setTimeout</span><span style="color: Olive;">(</span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Gray;">,</span><span style="color: Maroon;">0</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp; &nbsp; </span></li>
<li><span style="color: Olive;">})()</span><span style="color: Gray;">;</span></li></ol></div>
<p>最后我们可以封装出这样一个方法：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">TUI</span><span style="color: Gray;"> = </span><span style="color: Teal;">window</span><span style="color: Gray;">.$ = </span><span style="color: Olive;">{}</span><span style="color: Gray;">;</span></li>
<li><span style="color: #ffa500;">/**</span></li>
<li><span style="color: #ffa500;"> * @public 通过iframe异步请求数据</span></li>
<li><span style="color: #ffa500;"> * @param {string}&nbsp; url是请求的地址</span></li>
<li><span style="color: #ffa500;"> * @param {function}&nbsp; cb是处理返回数据的回调函数</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">getIframeData</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">url</span><span style="color: Gray;">, </span><span style="color: Blue;">cb</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">f</span><span style="color: Gray;"> = </span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">getElementById</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">crossdomain</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Blue;">f</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">f</span><span style="color: Gray;">.</span><span style="color: Blue;">src</span><span style="color: Gray;"> = </span><span style="color: Blue;">url</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">else</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">t</span><span style="color: Gray;"> = </span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">createElement</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">DIV</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">t</span><span style="color: Gray;">.</span><span style="color: Blue;">innerHTML</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">'</span><span style="color: Red;">&lt;iframe id=&quot;crossdomain&quot; width=&quot;0&quot; height=&quot;0&quot; style=&quot;visibility:hidden;&quot; src=&quot;</span><span style="color: #8b0000;">'</span><span style="color: Gray;"> + </span><span style="color: Blue;">url</span><span style="color: Gray;"> + </span><span style="color: #8b0000;">'</span><span style="color: Red;">&quot; &gt;&lt;/iframe&gt;</span><span style="color: #8b0000;">'</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">body</span><span style="color: Gray;">.</span><span style="color: Blue;">appendChild</span><span style="color: Olive;">(</span><span style="color: Blue;">t</span><span style="color: Gray;">.</span><span style="color: Blue;">firstChild</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">try</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">cb</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">getElementById</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">crossdomain</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">contentWindow</span><span style="color: Gray;">.</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">body</span><span style="color: Gray;">.</span><span style="color: Blue;">getElementsByTagName</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">TEXTAREA</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)[</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">.</span><span style="color: Blue;">value</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Green;">catch</span><span style="color: Olive;">(</span><span style="color: Blue;">e</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">setTimeout</span><span style="color: Olive;">(</span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Gray;">,</span><span style="color: Maroon;">0</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #ffa500;">//像这样执行</span></li>
<li><span style="color: Gray;">$.</span><span style="color: Blue;">getIframeData</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">http://yoursite.com/request_url/</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">data</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: #ffa500;">/* do something */</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>只要再增加一个可选的param参数，这就是一个很标准的jQuery AJAX API，我们还可以在jQuery的$.get上面封装，增加一个是否跨域的判断，当这个request的URI修改成同样的域名后，自动切换到普通的AJAX方法来请求，把返回的文本用类似这样的正则/<(textarea)>(.+)<\/(textarea)>/删掉多余的字符，再传给回调函数，前端和服务器端都不用修改代码。</p>
<h3>五、用iframe直接请求数据的缺陷</h3>
<p>必须指出的是，iframe在ie里获取数据时会引发一些“小问题”，dojo的创始人Alex Russell把它们称作<a target="_blank" href="http://alex.dojotoolkit.org/2006/02/what-else-is-burried-down-in-the-depths-of-googles-amazing-javascript/">“灵异点击（phantom click）”和“噩梦般的指示器（throbber of doom）”</a>，前者是指在iframe请求内容的时候会出现一次点击链接的音效（让用户怀疑闹鬼，多差的体验口牙！），后者是指iframe加载过程中，ie的界面上会出现正在读取的提示（比如左下的进度条，右上的图标）……好罢，其实以我个人的标准，这两个问题都可以无视……</p>
<p>这种方法还有一个明显的缺陷，就是只支持GET类型的请求。</p>
<h3>六、用iframe结合ajax</h3>
<p>不过iframe还有一种使用方法，不但可以避免上面提到的问题，也不需要服务器端做任何调整，简单来说：在iframe的src里调用一个包含ajax方法的页面，然后父页面调用这个方法来发起跟子页面同域名下的ajax请求。在土豆网的播放页面上，我使用这种方法请求用户评论统一接口里的HTML内容，例如这个WH40K:DOWII的视频：</p>
<p><a  target="_blank" href="http://www.tudou.com/programs/view/iPcprDz_LhI/">http://www.tudou.com/programs/view/iPcprDz_LhI/</a></p>
<p>获得评论部分HTML的接口类似这样:</p>
<p><a  target="_blank" href=" http://comments.tudou.com/itemcomment.srv?method=get&#038;iid=21283123&#038;page=1&#038;tm=5&#038;ban=1">http://comments.tudou.com/itemcomment.srv?method=get&#038;iid=21283123&#038;page=1&#038;tm=5&#038;ban=1</a></p>
<p>这个接口在独立的一组服务器上实现，在视频播放页，豆单播放页，豆单封面，相册，个人主页都会被调用。由于包含大量用户提交的内容和复杂的HTML结构，如果用JSON形式，前端后端处理起来都效率低，此外，提交新评论，回复，删除，也会用到comments.tudou.com这个域名下的接口，而这些操作显然需要POST类型的请求。在这种需求下，借助iframe的AJAX方法</p>
<p>首先在comments.tudou.com域名下部署一个供iframe调用的跨域文件，感觉很像flashplayer的crossdomain.xml……</p>
<p><a  target="_blank" href="http://comments.tudou.com/crossdomain/index.html">http://comments.tudou.com/crossdomain/index.html</a></p>
<p>可以看到源文件里仅仅包含一个stand-alone的ajax方法……呃……你觉得很眼熟？不用怀疑，就是在jQuery源代码的基础上修改来的-___-b，支持最基本的需求。这个页面可以设置很长的过期头让浏览器缓存起来，因为不会再有变动。</p>
<p>在父页面里通过<a target="_blank" href="http://js.tudouui.com/js/comments_9.js">TUI.videoComment.request</a>提供统一的接口，不做详述了，只列举其中访问跨域方法的部分：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">try</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; $</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">#crossdomain</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)[</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">.</span><span style="color: Blue;">contentWindow</span><span style="color: Gray;">.</span><span style="color: Blue;">TUI</span><span style="color: Gray;">.</span><span style="color: Blue;">ajax</span><span style="color: Olive;">(</span><span style="color: Blue;">o</span><span style="color: Olive;">)</span><span style="color: Gray;">;&nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Green;">catch</span><span style="color: Olive;">(</span><span style="color: Blue;">e</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">setTimeout</span><span style="color: Olive;">(</span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Gray;">,</span><span style="color: Maroon;">500</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp; &nbsp; </span></li>
<li><span style="color: Olive;">})()</span><span style="color: Gray;">;</span></li></ol></div>
<h3>七、总结一下</h3>
<p>iframe适用于 ( 跨域的 &#038;&#038; ( 返回大量数据 || 返回HTML内容 || 需要发POST请求 ) ) 的场合，除此之外还有<a  target="_blank" href="http://www.ibm.com/developerworks/cn/web/wa-lo-comet/">comet里的串流技术（streaming）</a>——本文不涉及。使用时需要注意保持资源的纯粹性，并尽可能隐藏那些跟其他异步请求差异很大的或包含hack的细节（比如嵌入iframe，触发回调函数，处理数据），设计出一致的，兼容性和扩展性良好的，不碍眼的接口XD</p>
<p>关于跨域还要补充一点：修改document.domain可能会产生一些无法预料的问题，比如在firefox里，document.styleSheets的cssRules属性会被拒绝访问。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2008/12/31/iframe-cross-site-request/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>递归和递推：javascript求斐波那契数列的尾递归方法</title>
		<link>http://www.limboy.com/2008/11/22/javascript-tail-recursion/</link>
		<comments>http://www.limboy.com/2008/11/22/javascript-tail-recursion/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 14:48:16 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[代码]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2008/11/23/javascript-tail-recursion/</guid>
		<description><![CDATA[刚才在IBM DW上看到这篇《JavaScript 技巧与高级特性》，其中关于arguments.callee的部分有一个用递归来求斐波那契数列的例子，简化一下是这样的：
//经典递归
function&#160;fibonacci(n) {&#160;
&#160; &#160; return&#160;(function(n) {&#160;
&#160; &#160; &#160; &#160; if&#160;(n == 1 &#124;&#124; n == 2)&#160;
&#160; &#160; &#160; &#160; &#160; &#160; return&#160;1; 
&#160; &#160; &#160; &#160; return&#160;arguments.callee(n - 1) + arguments.callee(n - 2); 
&#160; &#160; })(n); 
}&#160;
&#160;
fibonacci(4); //result: 3
fibonacci(5); //result: 5
fibonacci(10); //result: 55
这种教科书式的写法出镜率很高，在很多文章里都可以看到，但是速度也特别慢，曾经看到过有些人就拿这种例子来说明“递归的效率低”或者“用javascript做函数式编程效率低”，然后给出迭代的写法……
更新：我今天老老实实的读了SICP的第一章之后发现书中对这个问题其实有很严谨的解释，为了防止自己被骂成民科，赶紧修正了一些说法，加了删除线的文字都是有错误的，新增加的文字用粗体。
其实这个方法速度慢并不是函数式编程（FP）的错，首先要把词义弄清楚，真正的数学意义上的“递归”（recursive）包含了“递推”（recurrence）和“回归”（regression）的过程，在程序执行的过程中，“递归”（recursive）指的是一种方法，把大的复杂的问题分解成更小更简单的问题，逐级分解下去，直到问题的规模小到可以直接求解，然后再逐级向上回溯直到解决最初的问题，用程序来实现这种算法的时候至少包含一次以上的递推执行过程，效率当然比不上直接作一次迭代。递归的计算过程（recursive process）包含了两个阶段，先逐级扩展（expansion），构造起一个由被推迟的操作组成的链条（会被解释器保存在堆栈里），然后在收缩（contraction）阶段逐级回溯执行那些操作。随着递归计算步骤的增多，这种方法消耗的资源会越来越大，而且会包含越来越多的冗余操作，上面那个求斐波那契数列的例子（在SICP里被称作“树形递归”）在这方面问题尤其严重，因为它的计算步骤会随着参数而指数性的增长。
引用SICP上的图解：

而在编程里常说的递归其实就是简单的指“自己调用自己”的过程，指的是一种语法形式，而不是计算过程，在SICP里使用“递归过程”（recursive procedure）这个词来称呼，表示“一个过程的定义中引用了该过程本身”，在FP里就是一个函数把状态作为参数反复调用自己，来实现迭代的效果，所以未必需要递推一次以上。，用递归过程也可以产生出迭代计算过程（iterative process，迭代计算过程中消耗的资源是一个常量），递归==迭代，这个表达式不仅在lisp,Erlang这类FP语言里成立，在javascript里也一样。
比如那个求斐波那契数列的例子就可以用尾递归：
//尾递归
function&#160;fibonacci(n) {&#160;
&#160; &#160; return&#160;(function(n1, n2, i) {&#160;
&#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>刚才在IBM DW上看到这篇<a target="_blank" href="http://www.ibm.com/developerworks/cn/web/wa-lo-dojoajax1/?ca=drs-tp4408">《JavaScript 技巧与高级特性》</a>，其中关于arguments.callee的部分有一个用递归来求斐波那契数列的例子，简化一下是这样的：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">//经典递归</span></li>
<li><span style="color: Green;">function</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fibonacci</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Gray;"> == </span><span style="color: Maroon;">1</span><span style="color: Gray;"> || </span><span style="color: Blue;">n</span><span style="color: Gray;"> == </span><span style="color: Maroon;">2</span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Maroon;">1</span><span style="color: Gray;">; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Gray;"> - </span><span style="color: Maroon;">1</span><span style="color: Olive;">)</span><span style="color: Gray;"> + </span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Gray;"> - </span><span style="color: Maroon;">2</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})(</span><span style="color: Blue;">n</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span></li>
<li><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">fibonacci</span><span style="color: Olive;">(</span><span style="color: Maroon;">4</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//result: 3</span></li>
<li><span style="color: Blue;">fibonacci</span><span style="color: Olive;">(</span><span style="color: Maroon;">5</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//result: 5</span></li>
<li><span style="color: Blue;">fibonacci</span><span style="color: Olive;">(</span><span style="color: Maroon;">10</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//result: 55</span></li></ol></div>
<p>这种教科书式的写法出镜率很高，在很多文章里都可以看到，但是速度也特别慢，曾经看到过有些人就拿这种例子来说明“递归的效率低”或者“用javascript做函数式编程效率低”，然后给出迭代的写法……</p>
<p><strong style="color:#ff0000">更新：我今天老老实实的读了<a href="http://www.douban.com/subject/1148282/" target="_blank">SICP</a>的第一章之后发现书中对这个问题其实有很严谨的解释，为了防止自己被骂成民科，赶紧修正了一些说法，加了删除线的文字都是有错误的，新增加的文字用粗体。</strong><span id="more-199"></span></p>
<p>其实这个方法速度慢并不是函数式编程（FP）的错，首先要把词义弄清楚，<del datetime="2008-11-23T13:37:36+00:00">真正的数学意义上的“递归”（recursive）包含了“递推”（recurrence）和“回归”（regression）的过程，</del><span style="color:#990000">在程序执行的过程中，“递归”（recursive）指的是一种方法，</span>把大的复杂的问题分解成更小更简单的问题，逐级分解下去，直到问题的规模小到可以直接求解，然后再逐级向上回溯直到解决最初的问题，<del datetime="2008-11-23T13:37:36+00:00">用程序来实现这种算法的时候至少包含一次以上的递推执行过程，效率当然比不上直接作一次迭代。</del><span style="color:#990000">递归的计算过程（recursive process）包含了两个阶段，先逐级扩展（expansion），构造起一个由被推迟的操作组成的链条（会被解释器保存在堆栈里），然后在收缩（contraction）阶段逐级回溯执行那些操作。随着递归计算步骤的增多，这种方法消耗的资源会越来越大，而且会包含越来越多的冗余操作，上面那个求斐波那契数列的例子（在SICP里被称作“树形递归”）在这方面问题尤其严重，因为它的计算步骤会随着参数而指数性的增长。</span></p>
<p>引用SICP上的图解：<br />
<img src="http://mitpress.mit.edu/sicp/full-text/book/ch1-Z-G-13.gif" alt="scip" /></p>
<p>而在编程里常说的递归其实就是简单的指“自己调用自己”的过程，<span style="color:#990000">指的是一种语法形式，而不是计算过程，在SICP里使用“递归过程”（recursive procedure）这个词来称呼，表示“一个过程的定义中引用了该过程本身”，</span>在FP里就是一个函数把状态作为参数反复调用自己，<del datetime="2008-11-23T13:37:36+00:00">来实现迭代的效果，所以未必需要递推一次以上。</del>，<span style="color:#990000">用递归过程也可以产生出迭代计算过程（iterative process，迭代计算过程中消耗的资源是一个常量），</span>递归==迭代，这个表达式不仅在lisp,Erlang这类FP语言里成立，在javascript里也一样。</p>
<p>比如那个求斐波那契数列的例子就可以用尾递归：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">//尾递归</span></li>
<li><span style="color: Green;">function</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fibonacci</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">n1</span><span style="color: Gray;">, </span><span style="color: Blue;">n2</span><span style="color: Gray;">, </span><span style="color: Blue;">i</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">i</span><span style="color: Gray;"> &lt; </span><span style="color: Blue;">n</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> ? </span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Olive;">(</span><span style="color: Blue;">n2</span><span style="color: Gray;">, </span><span style="color: Blue;">n1</span><span style="color: Gray;">+</span><span style="color: Blue;">n2</span><span style="color: Gray;">, </span><span style="color: Blue;">i</span><span style="color: Gray;">+</span><span style="color: Maroon;">1</span><span style="color: Olive;">)</span><span style="color: Gray;"> : </span><span style="color: Blue;">n1</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})(</span><span style="color: Maroon;">1</span><span style="color: Gray;">,</span><span style="color: Maroon;">1</span><span style="color: Gray;">,</span><span style="color: Maroon;">1</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>跟这样的迭代方法是完全等价的：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">//等价的循环</span></li>
<li><span style="color: Green;">function</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">fibonacci</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">n1</span><span style="color: Gray;"> = </span><span style="color: Blue;">n2</span><span style="color: Gray;"> = </span><span style="color: Blue;">s</span><span style="color: Gray;"> = </span><span style="color: Blue;">i</span><span style="color: Gray;"> = </span><span style="color: Maroon;">1</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">for</span><span style="color: Olive;">(</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;">&lt;</span><span style="color: Blue;">n</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;">++</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">s</span><span style="color: Gray;"> = </span><span style="color: Blue;">n1</span><span style="color: Gray;"> + </span><span style="color: Blue;">n2</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">n1</span><span style="color: Gray;"> = </span><span style="color: Blue;">n2</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">n2</span><span style="color: Gray;"> = </span><span style="color: Blue;">s</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">n1</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>速度测试：</p>
<p><iframe src="http://www.limboy.com/demo/recursion.html" style="width:400px;height:180px;" ></iframe></p>
<p>都是从数列的起始处开始递推，区别只是：在迭代方法里是把每两个相邻的数相加的和保存在循环体外部的局部变量里，在尾递归方法中是把这个和作为参数传给下一次函数调用。</p>
<p>附带说一下，“尾递归”（Tail Recursion）指的是<del datetime="2008-11-23T13:37:36+00:00">把计算过程集中在函数递归调用的最后一次</del><span style="color:#990000">把每次函数递归调用中的所有运算结果或操作都逐步传递到最末尾一次的函数调用，</span>FP语言在编译/解释的时候都会把尾递归优化成一次直接的运算，而在javascript引擎里就算没有优化，至少也可以在每次调用过程中不留下任何痕迹，可以像普通的循环语句那样线性的推算到最后，因此无论速度还是内存消耗，都跟普通的迭代方法没有区别。</p>
<p><a href='http://www.limboy.com/wp-content/uploads/2008/11/ascending_and_descending.jpg' target="_blank"><img src='http://www.limboy.com/wp-content/uploads/2008/11/ascending_and_descending.jpg' style="width:200px;" /></a><br />
<br/><br/><br />
==============正文结束的分割线=================<br />
<br/><br/><br />
吐槽时间到～</p>
<p>关于javascript的尾递归我估计肯定有很多人写过，<a target="_blank" href="http://osteele.com/">Oliver Steele</a>这样的大神就不用说了，中文的应该也有很多，我都懒得去google，所以如果火星了请一定要谅解………</p>
<p>我决定还是要尽量克服这种“火星恐惧症”，因为如果总是担心要写的东西太老土太平常太小白或是已经被人写过，大概就没办法在blog上交流技术了。我最近因为人际关系和情感上的问题比以前更自闭了，没心情写blog，没动力在javaeye发帖子，也没兴趣在IM上跟人说话……前几天跟一个在北京IBM做前端开发的同学说了几句话，好像是几个月来第一次跟陌生人交流……对了顺便说一下，在IM上找我的时候，请务必在第一句话里说明意图，即使在我被外向虚荣亢奋型人格占据的时间段里，对于只说一句“Hi”的聊天窗口，我也是会觉得不知所措并产生抗拒心理的……</p>
<p>最近准备参加两场技术交流活动，一个是29日的<a target="_blank" href="http://www.d2forum.org/d2/3/index.html">D2前端技术论坛</a>，这次因为在魔都举办，所以我们土豆在名义和物质上是主办方，托CTO的关系在徐家汇微软的地盘借了一处场子（由于以前空空荡荡的土豆仓库早就被新员工挤满，还有一大堆门禁，不适合举办活动），但是听说报名人数已经超过500，场子装不下必须做筛选了……</p>
<p>之所以用“听说”这个词是因为我没参与任何组织工作，到时候也不用被推上台讲啥，自闭还是有好处的挖哈哈哈哈～～当初跟<a target="_blank" href="http://www.mikkolee.com/">小麦</a>同学讨论的时候，我建议请国外强者来撑场面，比如南征北战的javascript福音战士，Mozilla的John Resig，可惜没人推动……</p>
<p>另一个活动是12月4日在帝都举办的<a target="_blank" href="http://www.sd2china2008.com/">SD2.0大会</a>，尽管在大萧条的背景下，我仍然义无反顾的在infoQ花1000rmb买了票……结果<a target="_blank" href="http://friendfeed.com/e/129442c7-6cc7-5163-76db-47c26146ceef/555-infoQ-SD2-0-CSDN-YY-P-YY/">被证明投资失误</a>……</p>
<p>如果吐槽的字数超过正文当然会是很囧的事情，所以虽然好久没在blog上写东西，我还是尽快收尾算了：</p>
<p>1，这个blog主要作为发布文章和项目的地方，所以如果我没有谷出自己喜欢的新鲜货，就不会有更新。我平时的更新多数都在twitter和friendfeed上。</p>
<p>2，我把twitter作为日常吐槽的地方，优点是可以约束我少写字，另外，我把twitter当作微博客而不是聊天/短信工具来使用：</p>
<p><a target="_blank" href="http://twitter.com/dexteryy">http://twitter.com/dexteryy</a></p>
<p>3，我的分享主要发布在friendfeed，这是我目前最喜欢最常用依赖程度仅次于google reader的应用，欢迎订阅～</p>
<p><a target="_blank" href="http://friendfeed.com/dexteryy">http://friendfeed.com/dexteryy</a></p>
<p>好了，趁着捣鼓斐波那契数列的热情，我要去看SICP和算法导论了……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2008/11/22/javascript-tail-recursion/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>新项目&#8221;YyOPML&#8221;——把OPML转换成web界面——大家一起来晒feed订阅列表吧！</title>
		<link>http://www.limboy.com/2008/05/31/yyopml-release/</link>
		<comments>http://www.limboy.com/2008/05/31/yyopml-release/#comments</comments>
		<pubDate>Fri, 30 May 2008 17:28:30 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web2.0]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[web服务/应用]]></category>
		<category><![CDATA[界面]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2008/05/31/yyopml-release/</guid>
		<description><![CDATA[首先要说一下目前的矛盾现状：一方面feed订阅和在线阅读器都还不够普及，多数普通网民就算经常访问blog网站，也还没养成订阅的习惯，主要还是通过门户媒体获取资讯，另一个方面，较早开始接触RSS订阅的人——特别是那些blogger和互联网geek们——不但已经对各种在线或离线的阅读器了如指掌，把阅读feed变成了上网的主要活动和习惯，而且很多人收集的feed已经多到让自己烦恼焦虑的程度。后者努力的整理删减自己的订阅列表，前者却经常抱怨不知道怎么寻找可订阅的信息来源…………这种不平衡于是引发了一种禁断的活动——朋友之间交换OPML订阅列表……
OPML是Google Reader乃至所有阅读器都支持导入导出的一种XML规范的“大纲(outline)”数据文件（题头图片里那个蓝色的方块就是OPML的标志，跟feed的著名橙色标志对应，说实话写文前我还不知道OPML也有标志……囧），通常包含用户订阅的所有feed，之所以说是“禁断”……是因为交换这种文件，直接导入到双方的阅读器里之后，很容易使信息爆炸的程度翻倍，而且对于这些导入的feed，不能像原主人那样清楚来历和订阅的理由，于是也不知道该如何看……因此直接交换的下场通常都很惨……
这个项目就是我的解决方案：让导出的OPML源文件支持直接在浏览器里作为网页来展示，而界面上使用完全展开的并排布局，可以像hao123或谷歌网站导航那样一目了然的查找网址，让访问者自己来挑选值得订阅的feed。(不过，你要有使用标签分类feed的习惯，否则显示效果肯定不好…不过那样的话，就算用常规的树状布局，效果也很差的…)
以下是示例页面，这里的“dexteryy.xml”就是我从自己的google reader里导出的OPML文件，包含完整的订阅列表：
http://www.limboy.com/yyopml/dexteryy.xml
还有谁像我一样没什么隐私担心暴露愿意分享OPML的话，可以留下网址或opml文件，我会收集到上面来……
项目主页：http://code.google.com/p/yyopml/
下载程序源码：http://code.google.com/p/yyopml/downloads/list
使用方法是：用文本编辑器打开OPML文件，在第一行后面加上以下内容：
&#60;?xml-stylesheet href=&#34;style/yyopml.xsl&#34; type=&#34;text/xsl&#34;?&#62;
然后跟解压出来的style目录一起传到服务器上，保持在同一个目录里，就可以直接用浏览器看opml文件了。
目前我提供的界面主题有两种，都是如上所说的“网站导航”风格，一个是灰色的面板风格（默认），一个是GOOGLE风格，对应的CSS文件分别是style/ui/yyopml_panel.css和style/ui/yyopml_google.css
支持在页面里切换皮肤，如果要更换默认皮肤，请修改style/ui/yyopml.js里的以下代码：
theme = theme &#124;&#124; &#34;panel&#34;;
把“panel”换成你要改成默认设置的css文件的后缀，比如&#8221;google&#8221;。
也可以在网址里加上参数，直接调用某种皮肤，比如&#8221;http://www.limboy.com/yyopml/dexteryy.xml#theme=google&#8220;，可以用google风格作为默认皮肤打开页面。
==================面向Coder的分界线====================
源码包括一个用来把XML转换成HTML来显示的XSL文件，和界面效果相关的文件。其中yy_core.js是我开发中的一个轻量级/FP风格的javascript库，很多代码都基于jquery，同名的方法接口也尽量跟jquery保持一致，命名空间跟土豆网的js库一样叫“TUI”，提供DOM选择器（我重写的精简功能）和一些常用工具，比jquery小很多(压缩后12k)，这个东西其实年初就想发出来……但是后来懒了，这次考虑到完成度的问题，也懒得在google code里开项目了，源码包里的yy_core.js是一个base64压缩过的版本……
另外，yyopml.js里有一个滚动条插件，是做这个项目的时候心血来潮写的，可以用类似这样的代码：$(&#8220;.list&#8221;).scrollbar(); 给那些外部容器overflow:hidden，内部容器高度超长的元素加上CSS定义的滚动条，支持鼠标滚轮，因为是基于“迷你jquery”来开发，所以应该很容易改成jquery的插件，厌倦了overflow:scroll滚动条的同学可以参考一下。
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2008/05/31/yyopml-release/rss-opmljpg-2/' rel='attachment wp-att-194' title='rss-opml.jpg'><img src='http://www.limboy.com/wp-content/uploads/2008/06/rss-opml.jpg' alt='rss-opml.jpg' style="float:left;border:0;margin:0 5px 5px 0;" /></a>首先要说一下目前的矛盾现状：一方面feed订阅和在线阅读器都还不够普及，多数普通网民就算经常访问blog网站，也还没养成订阅的习惯，主要还是通过门户媒体获取资讯，另一个方面，较早开始接触RSS订阅的人——特别是那些blogger和互联网geek们——不但已经对各种在线或离线的阅读器了如指掌，把阅读feed变成了上网的主要活动和习惯，而且很多人收集的feed已经多到让自己烦恼焦虑的程度。后者努力的整理删减自己的订阅列表，前者却经常抱怨不知道怎么寻找可订阅的信息来源…………这种不平衡于是引发了一种禁断的活动——朋友之间交换OPML订阅列表……<span id="more-192"></span></p>
<p>OPML是Google Reader乃至所有阅读器都支持导入导出的一种XML规范的“大纲(outline)”数据文件（题头图片里那个蓝色的方块就是OPML的标志，跟feed的著名橙色标志对应，说实话写文前我还不知道OPML也有标志……囧），通常包含用户订阅的所有feed，之所以说是“禁断”……是因为交换这种文件，直接导入到双方的阅读器里之后，很容易使信息爆炸的程度翻倍，而且对于这些导入的feed，不能像原主人那样清楚来历和订阅的理由，于是也不知道该如何看……因此直接交换的下场通常都很惨……</p>
<p>这个项目就是我的解决方案：让导出的OPML源文件支持直接在浏览器里作为网页来展示，而界面上使用完全展开的并排布局，可以像hao123或谷歌网站导航那样一目了然的查找网址，让访问者自己来挑选值得订阅的feed。(不过，你要有使用标签分类feed的习惯，否则显示效果肯定不好…不过那样的话，就算用常规的树状布局，效果也很差的…)</p>
<p>以下是示例页面，这里的“dexteryy.xml”就是我从自己的google reader里导出的OPML文件，包含完整的订阅列表：</p>
<p><a href="http://www.limboy.com/yyopml/dexteryy.xml" target="_blank">http://www.limboy.com/yyopml/dexteryy.xml</a></p>
<p>还有谁像我一样没什么隐私担心暴露愿意分享OPML的话，可以留下网址或opml文件，我会收集到上面来……</p>
<p>项目主页：<a href="http://code.google.com/p/yyopml/" target="_blank">http://code.google.com/p/yyopml/</a></p>
<p>下载程序源码：<a href="http://code.google.com/p/yyopml/downloads/list" target="_blank" target="_blank">http://code.google.com/p/yyopml/downloads/list</a></p>
<p>使用方法是：用文本编辑器打开OPML文件，在第一行后面加上以下内容：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;?</span><span style="color: Green;">xml-stylesheet</span><span style="color: Gray;"> </span><span style="color: #00008b;">href</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">style/yyopml.xsl</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">type</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">text/xsl</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">?&gt;</span></li></ol></div>
<p>然后跟解压出来的style目录一起传到服务器上，保持在同一个目录里，就可以直接用浏览器看opml文件了。</p>
<p>目前我提供的界面主题有两种，都是如上所说的“网站导航”风格，一个是灰色的面板风格（默认），一个是GOOGLE风格，对应的CSS文件分别是style/ui/yyopml_panel.css和style/ui/yyopml_google.css</p>
<p>支持在页面里切换皮肤，如果要更换默认皮肤，请修改style/ui/yyopml.js里的以下代码：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">theme</span><span style="color: Gray;"> = </span><span style="color: Blue;">theme</span><span style="color: Gray;"> || </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">panel</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li></ol></div>
<p>把“panel”换成你要改成默认设置的css文件的后缀，比如&#8221;google&#8221;。</p>
<p>也可以在网址里加上参数，直接调用某种皮肤，比如&#8221;<a href="http://www.limboy.com/yyopml/dexteryy.xml#theme=google" target="_blank">http://www.limboy.com/yyopml/dexteryy.xml#theme=google</a>&#8220;，可以用google风格作为默认皮肤打开页面。</p>
<p>==================面向Coder的分界线====================</p>
<p>源码包括一个用来把XML转换成HTML来显示的XSL文件，和界面效果相关的文件。其中yy_core.js是我开发中的一个轻量级/FP风格的javascript库，很多代码都基于jquery，同名的方法接口也尽量跟jquery保持一致，命名空间跟土豆网的js库一样叫“TUI”，提供DOM选择器（我重写的精简功能）和一些常用工具，比jquery小很多(压缩后12k)，这个东西其实年初就想发出来……但是后来懒了，这次考虑到完成度的问题，也懒得在google code里开项目了，源码包里的yy_core.js是一个base64压缩过的版本……</p>
<p>另外，yyopml.js里有一个滚动条插件，是做这个项目的时候心血来潮写的，可以用类似这样的代码：$(&#8220;.list&#8221;).scrollbar(); 给那些外部容器overflow:hidden，内部容器高度超长的元素加上CSS定义的滚动条，支持鼠标滚轮，因为是基于“迷你jquery”来开发，所以应该很容易改成jquery的插件，厌倦了overflow:scroll滚动条的同学可以参考一下。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2008/05/31/yyopml-release/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>JavaScript Memoization：让函数也有记忆功能</title>
		<link>http://www.limboy.com/2008/04/27/javascript_memoization/</link>
		<comments>http://www.limboy.com/2008/04/27/javascript_memoization/#comments</comments>
		<pubDate>Sun, 27 Apr 2008 02:57:54 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[代码]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2008/04/27/javascript_memoization/</guid>
		<description><![CDATA[realazy在blog上给出了一个JavaScript Memoization的实现，Memoization就是函数返回值的缓存，比如一个函数参数与返回结果一一对应的hash列表，wiki上其实也有详细解释，我不细说了，只讨论一下具体实现的问题，realazy文中的代码有一些问题，比如直接用参数拼接成的字符串作为查询缓存结果的key，如果参数里包括对象或数组的话，就很难保证唯一的key，还有1楼评论里提到的：[221,3]和[22,13]这样的参数也无法区分。 
那么来改写一下，首先还是用hash表来存放缓存数据：

function Memoize(fn){
&#160; &#160; var&#160;cache = {};
&#160; &#160; return&#160;function(){
&#160; &#160; &#160; &#160; var&#160;key = [];
&#160; &#160; &#160; &#160; for(&#160;var i=0, l = arguments.length; i &#60; l; i++ )&#160;
&#160; &#160; &#160; &#160; &#160; &#160; key.push(arguments[i]);
&#160; &#160; &#160; &#160; if( !(key&#160;in cache) )
&#160; &#160; &#160; &#160; &#160; &#160; cache[key] = fn.apply(this, arguments);
&#160; &#160; &#160; &#160; return&#160;cache[key];
&#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2008/04/ltp.jpg' title='ltp.jpg'><img src='http://www.limboy.com/wp-content/uploads/2008/04/ltp.jpg' alt='ltp.jpg' style="float:left;margin:0 10px 5px 0;width:200px;" /></a>realazy在blog上给出了一个<a target="_blank" href="http://realazy.org/blog/2008/04/22/javascript-memoization/">JavaScript Memoization的实现</a>，Memoization就是函数返回值的缓存，比如一个函数参数与返回结果一一对应的hash列表，wiki上其实也有<a target="_blank" href="http://en.wikipedia.org/wiki/Memoization">详细解释</a>，我不细说了，只讨论一下具体实现的问题，realazy文中的代码有一些问题，比如直接用参数拼接成的字符串作为查询缓存结果的key，如果参数里包括对象或数组的话，就很难保证唯一的key，还有1楼评论里提到的：[221,3]和[22,13]这样的参数也无法区分。 </p>
<p>那么来改写一下，首先还是用hash表来存放缓存数据：<span id="more-188"></span><br />
<br/><br/></p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Blue;">Memoize</span><span style="color: Olive;">(</span><span style="color: Blue;">fn</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">cache</span><span style="color: Gray;"> = </span><span style="color: Olive;">{}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">key</span><span style="color: Gray;"> = </span><span style="color: Olive;">[]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">for</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">i</span><span style="color: Gray;">=</span><span style="color: Maroon;">0</span><span style="color: Gray;">, </span><span style="color: Blue;">l</span><span style="color: Gray;"> = </span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;"> &lt; </span><span style="color: Blue;">l</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;">++ </span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">key</span><span style="color: Gray;">.</span><span style="color: Blue;">push</span><span style="color: Olive;">(</span><span style="color: Blue;">arguments</span><span style="color: Olive;">[</span><span style="color: Blue;">i</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;"> !</span><span style="color: Olive;">(</span><span style="color: Blue;">key</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">in</span><span style="color: Gray;"> </span><span style="color: Blue;">cache</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">cache</span><span style="color: Olive;">[</span><span style="color: Blue;">key</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: Blue;">fn</span><span style="color: Gray;">.</span><span style="color: Blue;">apply</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">cache</span><span style="color: Olive;">[</span><span style="color: Blue;">key</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>嗯，区别是直接把数组当作键来用，不过要注意函数里的arguments是js解释器实现的一个特殊对象，并不是真正的数组，所以要转换一下……</p>
<blockquote><p>
ps: 原来的参数包括方法名称和上下文引用：fib.fib_memo = Memoize(&#8216;fib_memo&#8217;, fib)，但实际上currying生成的函数里可以用this直接引用上层对象，更复杂的例子可以参考<a target="_blank" href="http://ejohn.org/blog/simple-class-instantiation/">John Resig的makeClass</a>，所以我改成直接传函数引用：fib.fib_memo = Memoize(fib.fib_memo)</p></blockquote>
<p>这样写看上去似乎很靠谱，由参数组成的数组不是唯一的么。但实际上，数组之所以能作为js对象的属性名称来使用，是因为它被当作字符串处理了，也就是说如果你给函数传的参数是这样：(1,2,3), cache对象就会是这个样子：{ &#8220;1,2,3&#8243;: somedata }，如果你的参数里有对象，比如：(1,2,{i:&#8221;yy&#8221;})，实际的键值会是：&#8221;1,2,[object Object]&#8220;，所以这跟把数组拼接成字符串的方法其实没有区别……</p>
<p>示例：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Gray;"> = </span><span style="color: Olive;">[</span><span style="color: Maroon;">1</span><span style="color: Gray;">,</span><span style="color: Maroon;">2</span><span style="color: Gray;">,</span><span style="color: Olive;">{</span><span style="color: Blue;">yy</span><span style="color: Gray;">:</span><span style="color: #8b0000;">'</span><span style="color: Red;">0</span><span style="color: #8b0000;">'</span><span style="color: Olive;">}]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">b</span><span style="color: Gray;"> = </span><span style="color: Olive;">[</span><span style="color: Maroon;">1</span><span style="color: Gray;">,</span><span style="color: Maroon;">2</span><span style="color: Gray;">,</span><span style="color: Olive;">{</span><span style="color: Blue;">xx</span><span style="color: Gray;">:</span><span style="color: #8b0000;">'</span><span style="color: Red;">1</span><span style="color: #8b0000;">'</span><span style="color: Olive;">}]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;"> = </span><span style="color: Olive;">{}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">obj</span><span style="color: Olive;">[</span><span style="color: Blue;">a</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">111</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Blue;">obj</span><span style="color: Olive;">[</span><span style="color: Blue;">b</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">222</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">for</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">i</span><span style="color: Gray;"> </span><span style="color: Green;">in</span><span style="color: Gray;"> </span><span style="color: Blue;">obj</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">alert</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">i</span><span style="color: Gray;"> + </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;"> = </span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> + </span><span style="color: Blue;">obj</span><span style="color: Olive;">[</span><span style="color: Blue;">i</span><span style="color: Olive;">]</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;">;&nbsp; &nbsp; </span><span style="color: #ffa500;">//只会弹出&quot;1,2,[object Object] = 222&quot;，obj[a] = &quot;111&quot;被覆盖了</span></li></ol></div>
<p>直接用参数作为键名的方法不靠谱了…………换一种方法试试：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Blue;">Memoize</span><span style="color: Olive;">(</span><span style="color: Blue;">fn</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">cache</span><span style="color: Gray;"> = </span><span style="color: Olive;">{}</span><span style="color: Gray;">, </span><span style="color: Blue;">args</span><span style="color: Gray;"> = </span><span style="color: Olive;">[]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">for</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">i</span><span style="color: Gray;">=</span><span style="color: Maroon;">0</span><span style="color: Gray;">, </span><span style="color: Blue;">key</span><span style="color: Gray;"> = </span><span style="color: Blue;">args</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;"> &lt; </span><span style="color: Blue;">key</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;">++ </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">equal</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">args</span><span style="color: Olive;">[</span><span style="color: Blue;">i</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp; </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">cache</span><span style="color: Olive;">[</span><span style="color: Blue;">i</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">args</span><span style="color: Olive;">[</span><span style="color: Blue;">key</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: Blue;">arguments</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">cache</span><span style="color: Olive;">[</span><span style="color: Blue;">key</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: Blue;">fn</span><span style="color: Gray;">.</span><span style="color: Blue;">apply</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">, </span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">cache</span><span style="color: Olive;">[</span><span style="color: Blue;">key</span><span style="color: Olive;">]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>可以完全避免上述问题，没有使用hash的键值对索引，而是把函数的参数和结果分别缓存在两个列表里，每次都先遍历整个参数列表作比较，找出对应的键名/ID号之后再从结果列表里取数据。以下是比较数组的equal方法：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Blue;">equal</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">first</span><span style="color: Gray;">, </span><span style="color: Blue;">second</span><span style="color: Gray;"> </span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;"> !</span><span style="color: Blue;">first</span><span style="color: Gray;"> || !</span><span style="color: Blue;">second</span><span style="color: Gray;"> || </span><span style="color: Blue;">first</span><span style="color: Gray;">.</span><span style="color: Blue;">constructor</span><span style="color: Gray;"> != </span><span style="color: Blue;">second</span><span style="color: Gray;">.</span><span style="color: Blue;">constructor</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">false</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">first</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;"> &amp;&amp; </span><span style="color: Green;">typeof</span><span style="color: Gray;"> </span><span style="color: Blue;">first</span><span style="color: Gray;"> != </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">string</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">&nbsp; </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">for</span><span style="color: Olive;">(</span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">i</span><span style="color: Gray;">=</span><span style="color: Maroon;">0</span><span style="color: Gray;">, </span><span style="color: Blue;">l</span><span style="color: Gray;"> = </span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">first</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;"> &gt; </span><span style="color: Blue;">second</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> ? </span><span style="color: Blue;">first</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;"> : </span><span style="color: Blue;">second</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;">&lt;</span><span style="color: Blue;">l</span><span style="color: Gray;">; </span><span style="color: Blue;">i</span><span style="color: Gray;">++</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;"> !</span><span style="color: Blue;">equal</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">first</span><span style="color: Olive;">[</span><span style="color: Blue;">i</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: Blue;">second</span><span style="color: Olive;">[</span><span style="color: Blue;">i</span><span style="color: Olive;">]</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Green;">return</span><span style="color: Gray;"> </span><span style="color: Green;">false</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">else</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Green;">typeof</span><span style="color: Gray;"> </span><span style="color: Blue;">first</span><span style="color: Gray;"> == </span><span style="color: #8b0000;">'</span><span style="color: Red;">object</span><span style="color: #8b0000;">'</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">for</span><span style="color: Olive;">(</span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">n</span><span style="color: Gray;"> </span><span style="color: Green;">in</span><span style="color: Gray;"> </span><span style="color: Blue;">first</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;"> !</span><span style="color: Blue;">equal</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">first</span><span style="color: Olive;">[</span><span style="color: Blue;">n</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: Blue;">second</span><span style="color: Olive;">[</span><span style="color: Blue;">n</span><span style="color: Olive;">]</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Green;">return</span><span style="color: Gray;"> </span><span style="color: Green;">false</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">else</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Blue;">first</span><span style="color: Gray;"> === </span><span style="color: Blue;">second</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">true</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>千万不要直接用==来比较arguments和args里的数组，那样比较的是内存引用，而不是参数的内容。</p>
<p>这种方法的速度很慢，equal方法其实影响不大，但是缓存的结果数量多了以后，每次都要遍历参数列表却是很没效率的（求80以上的fibonacci数列，在firefox3和safari3上都要40ms左右）</p>
<p>如果在实际应用中参数变动不多或者不接受参数的话，可以参考Oliver Steel的这篇<a target="_blank" href="http://osteele.com/archives/2006/04/javascript-memoization">《One-Line JavaScript Memoization》</a>，用很短的函数式风格解决问题：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Blue;">Memoize</span><span style="color: Olive;">(</span><span style="color: Blue;">o</span><span style="color: Gray;">, </span><span style="color: Blue;">p</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">f</span><span style="color: Gray;"> = </span><span style="color: Blue;">o</span><span style="color: Olive;">[</span><span style="color: Blue;">p</span><span style="color: Olive;">]</span><span style="color: Gray;">, </span><span style="color: Blue;">mf</span><span style="color: Gray;">, </span><span style="color: Blue;">value</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">s</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">v</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Green;">return</span><span style="color: Gray;"> </span><span style="color: Blue;">o</span><span style="color: Olive;">[</span><span style="color: Blue;">p</span><span style="color: Olive;">]</span><span style="color: Gray;">=</span><span style="color: Blue;">v</span><span style="color: Gray;">||</span><span style="color: Blue;">mf</span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">((</span><span style="color: Blue;">mf</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Olive;">()</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">(</span><span style="color: Blue;">s</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">value</span><span style="color: Olive;">}))</span><span style="color: Gray;">.</span><span style="color: Blue;">reset</span><span style="color: Gray;"> = </span><span style="color: Blue;">mf</span><span style="color: Gray;">.</span><span style="color: Blue;">reset</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">value</span><span style="color: Gray;"> = </span><span style="color: Blue;">f</span><span style="color: Gray;">.</span><span style="color: Blue;">apply</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">,</span><span style="color: Blue;">arguments</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//此处修改过，允许接受参数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">})</span><span style="color: Gray;">.</span><span style="color: Blue;">reset</span><span style="color: Gray;"> = </span><span style="color: Blue;">s</span><span style="color: Olive;">)()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>示例：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">fib</span><span style="color: Gray;"> = </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">temp</span><span style="color: Gray;">: </span><span style="color: Green;">function</span><span style="color: Olive;">(</span><span style="color: Blue;">n</span><span style="color: Olive;">){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">for</span><span style="color: Olive;">(</span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">i</span><span style="color: Gray;">=</span><span style="color: Maroon;">0</span><span style="color: Gray;">;</span><span style="color: Blue;">i</span><span style="color: Gray;">&lt;</span><span style="color: Maroon;">10000</span><span style="color: Gray;">;</span><span style="color: Blue;">i</span><span style="color: Gray;">++</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">n</span><span style="color: Gray;">=</span><span style="color: Blue;">n</span><span style="color: Gray;">+</span><span style="color: Maroon;">2</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">return</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">n</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">Memoize</span><span style="color: Olive;">(</span><span style="color: Blue;">fib</span><span style="color: Gray;">,</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">temp</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//让fib.temp缓存返回值</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">fib</span><span style="color: Gray;">.</span><span style="color: Blue;">temp</span><span style="color: Olive;">(</span><span style="color: Maroon;">16</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//执行结果：20006，被缓存</span></li>
<li><span style="color: Blue;">fib</span><span style="color: Gray;">.</span><span style="color: Blue;">temp</span><span style="color: Olive;">(</span><span style="color: Maroon;">20</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//执行结果：20006</span></li>
<li><span style="color: Blue;">fib</span><span style="color: Gray;">.</span><span style="color: Blue;">temp</span><span style="color: Olive;">(</span><span style="color: Maroon;">10</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//执行结果：20006</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">fib</span><span style="color: Gray;">.</span><span style="color: Blue;">temp</span><span style="color: Gray;">.</span><span style="color: Blue;">reset</span><span style="color: Olive;">()</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//重置缓存</span></li>
<li><span style="color: Blue;">fib</span><span style="color: Gray;">.</span><span style="color: Blue;">temp</span><span style="color: Olive;">(</span><span style="color: Maroon;">10</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: #ffa500;">//执行结果：20010</span></li></ol></div>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2008/04/27/javascript_memoization/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>iPhone App开发笔记</title>
		<link>http://www.limboy.com/2008/03/08/iphone-app-develop/</link>
		<comments>http://www.limboy.com/2008/03/08/iphone-app-develop/#comments</comments>
		<pubDate>Fri, 07 Mar 2008 19:04:13 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[web服务/应用]]></category>
		<category><![CDATA[界面]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2008/03/08/iphone-app-develop/</guid>
		<description><![CDATA[第一，标题里的app指的是根正苗红老实本分的Web App，昨天的这个时候，对是在昨天，iPhone Web App就等同于iPhone App，咳咳，虽然现在不是了，但我这笔记是两个星期前的……
第二，不全，主要是我关心的一些细节，以及我自己理解的一些东西……


&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;

html里可以调用系统接口，比如电话拨号：
&#60;a href=&#34;tel:1-408-555-5555&#34;&#62;1-408-555-5555&#60;/a&#62;
还有mail和google map的接口……

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;

在js里嗅探iphone的safari环境，要注意agent字符串里有额外两处：
&#8220;Mobile/1A543&#8243;，这个是iphone OS的操作系统版本（注意不是固件版本）
&#8220;iPhone&#8221;，这个是移动平台的类型，如果是ipod touch的话这里会是“ipod”
此外：
&#8220;version/3.0&#8243;，Safari的市场版本号
&#8220;Safari/419.3&#8243;，这个是build版本，虽然iphone跟osx一样都是safari3.0，但build版本号不同
完整的例子：
Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like
Gecko) Version/3.0 Mobile/1A543 Safari/419.3

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;

调用css的时候，media类型支持CSS3，比如可以用“only”来屏蔽旧浏览器，用“(min-device-width: 481px)”屏蔽小屏幕手机。由于iphone里的safari不支持print和handheld的media类型，可以用它们来对iphone屏蔽一些css文件。
示例：
&#60;link media=&#34;only screen and (min-device-width: 481px)&#34; href=&#34;not-small-device.css&#34; type=&#34;text/css&#34; rel=&#34;stylesheet&#34; &#62;
也可以作为css选择器里，比如
@media screen {&#160;
#text&#160;{ color: white; background-color: black; }&#160;
}
由于safari支持css3，你还可以享受到的福利包括在background里放6张图片做圆角，给文本加阴影，使用属性选择器之类……

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;

iphone的浏览器里有一个很重要的概念是viewport（视区），系统默认的viewport为980像素，可以用meta标签指定，宽度范围从200到10,000，高度范围从223到10,000，还可以使用user-scalable禁止用户缩放页面（常见的iphone web应用，比如facebook,google reader，因为要仿原生界面，都是这样设置的），minimum-scale和maximum-scale可以设置缩放的限制，initial-scale是默认的缩放程度，范围从>0到10
示例：
&#60;meta name=&#34;viewport&#34; content=&#34;width = 320&#34; /&#62;
&#60;meta&#160;name=&#34;viewport&#34; content=&#34;initial-scale=2.3, user-scalable=no&#34; /&#62;
iphone默认的浏览器窗口尺寸是:  竖向（body[orient="profile"]）为宽320px，高356px，横向（body[orient="landscape"]）为宽208px，高480px，但实际上这是显示了浏览器地址栏之后剩余的空间，往下拖动页面时，地址栏会隐藏，所以实际的viewport（竖向）是宽320px，高416px。
页面加载之后可以用 window.scrollTo(0, 1) 隐藏地址栏，自动使用最大化的viewport。
关于viewport，还有一个很重要的概念是：iphone的safari浏览器完全没有滚动条，而且不是简单的“隐藏滚动条”，是根本没有这个功能。所以不但iframe, [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2008/03/08/iphone-app-develop/index_steps_2jpg/' rel='attachment wp-att-184' title='index_steps_2.jpg'><img src='http://www.limboy.com/wp-content/uploads/2008/03/index_steps_2.jpg' alt='index_steps_2.jpg' style="width:200px;float:left;margin:0 5px 0 0;border:0;" /></a>第一，标题里的app指的是根正苗红老实本分的<a href="http://www.apple.com/webapps/" target="_blank">Web App</a>，昨天的这个时候，对是在昨天，iPhone Web App就等同于iPhone App，咳咳，虽然现在不是了，但我这笔记是两个星期前的……</p>
<p>第二，不全，主要是我关心的一些细节，以及我自己理解的一些东西……<span id="more-182"></span><br />
<br/><br />
<br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>html里可以调用系统接口，比如电话拨号：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">a</span><span style="color: Gray;"> </span><span style="color: #00008b;">href</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">tel:1-408-555-5555</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span><span style="color: Gray;">1-408-555-5555</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">a</span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>还有mail和google map的接口……</p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>在js里嗅探iphone的safari环境，要注意agent字符串里有额外两处：</p>
<p>&#8220;Mobile/1A543&#8243;，这个是iphone OS的操作系统版本（注意不是固件版本）<br />
&#8220;iPhone&#8221;，这个是移动平台的类型，如果是ipod touch的话这里会是“ipod”</p>
<p>此外：</p>
<p>&#8220;version/3.0&#8243;，Safari的市场版本号<br />
&#8220;Safari/419.3&#8243;，这个是build版本，虽然iphone跟osx一样都是safari3.0，但build版本号不同</p>
<p>完整的例子：</p>
<blockquote><p>Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like<br />
Gecko) Version/3.0 Mobile/1A543 Safari/419.3</p></blockquote>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>调用css的时候，media类型支持CSS3，比如可以用“only”来屏蔽旧浏览器，用“(min-device-width: 481px)”屏蔽小屏幕手机。由于iphone里的safari不支持print和handheld的media类型，可以用它们来对iphone屏蔽一些css文件。<br />
示例：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">link</span><span style="color: Gray;"> </span><span style="color: #00008b;">media</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">only screen and (min-device-width: 481px)</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">href</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">not-small-device.css</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">type</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">text/css</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">rel</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">stylesheet</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>也可以作为css选择器里，比如</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #00008b;">@media</span><span style="color: Gray;"> </span><span style="color: Blue;">screen</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">#text</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: Green;">color:</span><span style="color: Gray;"> </span><span style="color: #00008b;">white</span><span style="color: Gray;">; </span><span style="color: Green;">background-color:</span><span style="color: Gray;"> </span><span style="color: #00008b;">black</span><span style="color: Gray;">; </span><span style="color: Olive;">}</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>由于safari支持css3，你还可以享受到的福利包括在background里放6张图片做圆角，给文本加阴影，使用属性选择器之类……</p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>iphone的浏览器里有一个很重要的概念是viewport（视区），系统默认的viewport为980像素，可以用meta标签指定，宽度范围从200到10,000，高度范围从223到10,000，还可以使用user-scalable禁止用户缩放页面（常见的iphone web应用，比如facebook,google reader，因为要仿原生界面，都是这样设置的），minimum-scale和maximum-scale可以设置缩放的限制，initial-scale是默认的缩放程度，范围从>0到10<br />
示例：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">meta</span><span style="color: Gray;"> </span><span style="color: #00008b;">name</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">viewport</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">content</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">width = 320</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span></li>
<li><span style="color: Olive;">&lt;</span><span style="color: Green;">meta</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">name</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">viewport</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">content</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">initial-scale=2.3, user-scalable=no</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span></li></ol></div>
<p>iphone默认的浏览器窗口尺寸是:  竖向（body[orient="profile"]）为宽320px，高356px，横向（body[orient="landscape"]）为宽208px，高480px，但实际上这是显示了浏览器地址栏之后剩余的空间，往下拖动页面时，地址栏会隐藏，所以实际的viewport（竖向）是宽320px，高416px。<br />
页面加载之后可以用 window.scrollTo(0, 1) 隐藏地址栏，自动使用最大化的viewport。</p>
<p>关于viewport，还有一个很重要的概念是：iphone的safari浏览器完全没有滚动条，而且不是简单的“隐藏滚动条”，是根本没有这个功能。所以不但iframe, overflow:scroll的元素没有滚动条，整个窗口也没有的，iphone的safari浏览器实际上从一开始就完整显示了这个网页，然后用viewport查看其中的一部分。当你用手指拖动时，其实拖的不是页面，而是viewport…………由此引申出的结果很多，比如CSS里的 position:fixed 无效……</p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>浏览器行为的改变不止是滚动条，交互事件也跟普通桌面不一样：</p>
<p>所有hover动作，还有mouseover，都不存在，链接上的title内容，会在你点击链接并按住不动时弹跳出来（如果你不放开手指，继续移动的话，点击事件不会发生，具体原因下面解释）…………而mouseover，直接转换成了mousedown……</p>
<p>点击页面元素之后发生的事情很复杂…………比如当你用单指按住可点击元素（大约就是默认为block的元素），然后放开，首先触发的event居然是mousemove！ 接下来如果元素内容不变（这个条件比较难理解，我知道），会陆续触发mousedown，mouseup，click，如果内容改变，就不会再触发任何事件……</p>
<p>如果你恰好不太走运的给网页上一些inline元素绑过js事件（这比较常见，我也知道），比如span，有一个不用修改标签的方法是给它们都加上onclick=&#8221;void(0)&#8221;，这样iphone就会认为它们是可点击的元素-_____-b</p>
<p>如果按住元素之后移动手指，当然就不要指望会触发mousemove了，啥事情都没有，不过停下的时候，会触发onscroll （因为你刚才移动了viewport嘛……）</p>
<p>如果你用两个手指做缩放的动作，啥事件都不会有啦，但是如果你用两个手指在屏幕上一起移动，而且所在的位置是一个本来有滚动条的页面元素(比如iframe罢)，会触发一个叫mousewheel的事件（但是别指望iframe本身的内容会滚动-___-b）, 停止移动时同样触发onscroll。</p>
<p>OK，你希望像平时那样用onmousedown,onmouseup,onmousemove来做页面元素的拖拽交互把iphone web app的界面做的像原生界面一样活蹦乱跳的梦想已经破灭了，请努力克制骂乔布斯的欲望。</p>
<p>对了，不用我说也应该想得到，onkeyup，e.charCode，e.keyCode这类玩意都不能用罢？</p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>默认的html控件的样式大家都已经知道很cool了，不过也可以自己修改，具体内容请查看《iphone用户界面指南》的第三章：<a href="http://developer.apple.com/documentation/iPhone/Conceptual/iPhoneHIG/MetricsLayout/chapter_5_section_1.html#//apple_ref/doc/uid/TP40006596-CH6-SW1" target="_blank">Metrics, Layout Guidelines, and Tips</a></p>
<p>iphone里的safari调整了默认的文字样式，这些调整被包括在了一个新的css属性“-webkit-text-size-adjust”里面，相当于“-webkit-text-size-adjust:auto;”，你可以覆盖它，根据需要改成none或者200%</p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>web app可以像原生应用一样，在home界面里上添加一个快捷方式图标，方法是增加一个link标签：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">link</span><span style="color: Gray;"> </span><span style="color: #00008b;">rel</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">apple-touch-icon</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">href</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">custom_icon.png</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span></li></ol></div>
<p>这是针对单个页面的，如果你把图片命名为“apple-touch-icon.png”，放在网站的某个目录里面，该目录下所有页面都会获得添加图标的功能……</p>
<p>图标的要求是尺寸57×57，png格式，不用画蛇添足的去做圆角渐变或玻璃反光效果，iphone系统会把图片自动裁剪和渲染成统一的风格……</p>
<p>喔对了……不要高兴太早……这个快捷图标的功能，只有1.1.3或更高的固件版本才支持……考虑到国内那些买旧版本破解机器还被商家反复叮嘱不要升级的用户……呃……</p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>关于网页中的媒体文件，普通图片最大支持200万像素（jpg的话，最大可以显示出3200万的，不过超过200万的jpg都会被压成缩略图），支持的最大尺寸是2 * 1024&#215;1024，gif动画最大支持2m（否则只显示第1帧）</p>
<p>iphone支持的视频格式：</p>
<blockquote><p>H.264 Baseline Profile Level 3.0 video, up to 640 x 480 at 30 fps. Note that B frames are not supported in the Baseline profile.<br />
MPEG-4 Part 2 video (Simple Profile)<br />
AAC-LC audio, up to 48 kHz<br />
.mov, .mp4, .m4v, .3gp file formats</p></blockquote>
<p>需要注意的是这里的“Baseline profile”，由于这种编码的质量跟“Extended Profile”和“main profile”相比效果比较差，目前主流的支持“高清”（h264）的视频网站，比如youtube，土豆，都没有采用Baseline profile压缩h264视频，所以iphone不但不能播放网络上流行的flv视频（因为不支持flash），连刚开始流行的h264也不能直接播放…………提供iphone应用的视频网站无法使用现有资源，不得不压缩iphone专用的视频文件，所以不要指望能立即在iphone上观看视频网站上的所有资源……T__T</p>
<p>由于iphone不支持flash播放器，视频文件只能直接嵌在页面里，用自带的quicktime来全屏播放，示例：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">embed</span><span style="color: Gray;"> </span><span style="color: #00008b;">src</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">screen.jpg</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">href</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">movie.m4v</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">type</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">video/x-m4v</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">target</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">myself</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">scale</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">1</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> ...</span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>更多细节请看官方文档：<a href="http://www.apple.com/quicktime/tutorials/embed.html" target="_blank">Including QuickTime In A Web Page</a></p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>如果想全面了解iphone上的web开发，推荐阅读：</p>
<p><a href="http://developer.apple.com/documentation/iPhone/Conceptual/iPhoneHIG/" target="_blank">iPhone Human Interface Guidelines</a>(官方还有一份名字类似的文档，简称OSXHIG，是<a href="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/" target="_blank">界面设计者的圣经</a>之一)</p>
<p><a href="http://developer.apple.com/documentation/AppleApplications/Reference/SafariWebContent/" target="_blank">Safari Web Content Guide for iPhone</a> </p>
<p><a href="http://developer.apple.com/internet/webcontent/bestwebdev.html" target="_blank">Web Page Development: Best Practices</a>(这篇可以凑合看看，2月8号刚更新过的)</p>
<p>此外，ADC on iTunes里有好多iphone相关的视频，讨厌翻文档的可以去弄来看看，这可是iTunes store里少有的免费资源喔……</p>
<p><br/><br />
<em style="color:#999;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;懒得想小标题的分界线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</em><br />
<br/></p>
<p>就像开头说的，这是2周前写的，一直懒得修改整齐了往blog上帖，但是昨天半夜（好罢是今天凌晨）在<a href="http://twitter.com/apple4us" target="_blank">twitter</a>上不小心看了iphone SDK发布的实况转播……我发现再拖延的话就只能贴到火星去了……</p>
<p>跟华丽的SDK相比，iphone safari上的开发环境可以说很糟糕，非常限制想象力——对javascript和RIA开发者来说，不过只要看看iphone用户上网的热情和相关数据，可以预见在很长一段时间里，iphone平台仍然会是立志开发web app的勇者们争夺的滩头阵地。</p>
<p>啊啊啊啊啊，2.10G的iphone_sdk.dmg终于下载完了，睡觉去……下周买<a href="http://www.china-pub.com/computers/common/info.asp?id=38686">《Cocoa入门&#8211;使用Objective-C》</a>……<br />
<br/><br />
<br/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2008/03/08/iphone-app-develop/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>DOM加载事件的终极解决方案</title>
		<link>http://www.limboy.com/2007/04/19/domready/</link>
		<comments>http://www.limboy.com/2007/04/19/domready/#comments</comments>
		<pubDate>Wed, 18 Apr 2007 17:08:37 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2007/04/19/domready/</guid>
		<description><![CDATA[今天被土豆网的lex鄙视了，因为我的BLOG在Safari里根本无法浏览——loading永远不会结束，很明显，这意味着webkit引擎不支持上次提到的判断DOM加载完成的方法。
既然开了新文章，就干脆重新回顾一下这个问题：如今的javascript编程非常依赖DOM（文档对象模型），对HTML和XML来说，DOM是一个应用程序接口 (API) ，对JS来说，DOM为文档创建了程序可以使用的对象和方法，DOM把前端程序和内容结合在一起，就好像ORM（对象-关系映射，比如PEAR库里的DB_DataObject）把后台程序和关系数据库结合在一起，形象点说它是一颗节点树，没有这棵树的支撑，很多JS方法就无法使用。
传统方式是通过window.onload事件来判断DOM是否加载完成，但实际上它的加载时间里还包括了img标签插入的图片、FLASH等大家伙，很多时候，来不及等这些东西都下载完成才执行JS（特别是当你要用JS给页面元素注册事件、调整外观，用AJAX加载重要内容）。所以必须有一种方法来单独判断DOM是否加载完成。
国外很早就有强者解决了这个问题，但我上次看的资料其实不完整（不求甚解的下场），最终的解决方案是在几个人的BLOG上讨论出来的……blogsphere（博客圈）果然是一种能激发创造性的社区结构……
首先是Dean Edwards指出了两件重要的工具：

Mozilla提供一个很棒的事件：DOMContentLoaded
微软支持defer属性，这并不是私有属性，而是包括在W3C的DOM 1标准里的，但是它似乎没有被XHTML支持，还有一个特点是，defer只能放在script标签里，而不能用JS来添加。

那么首先在Firefox上判断DOM加载完成就很简单了：
if (document.addEventListener)&#160;
{
&#160; &#160; document.addEventListener(&#34;DOMContentLoaded&#34;, init, false);
}
Opera9也支持上面的方法，但更低版本就不行了……
至于IE，最早提出的方法是把init函数放在一个单独的ie_onload.js里执行，在HTML调用脚本时加入条件注释和defer：
&#60;!--[if IE]&#62;&#60;script defer src=&#34;ie_onload.js&#34;&#62;&#60;/script&#62;&#60;![endif]--&#62;
或者：
&#60;!--[if IE]&#62;&#60;script defer src=&#34;javascript:'init()'&#34;&#62;&#60;/script&#62;&#60;![endif]--&#62;
这个方法的缺点是要在HTML里嵌入代码，缺乏灵活性，在Matthias Miller加入讨论后，产生了更方便的实现方法：
// for Internet Explorer
&#160; &#160; &#160; /*@cc_on @*/
&#160; &#160; &#160; /*@if (@_win32)
&#160; &#160; &#160; &#160; &#160; document.write(&#34;&#60;scr&#34;+&#34;ipt id=__ie_onload defer src=//0&#62;&#60;\/scr&#34;+&#34;ipt&#62;&#34;);
&#160; &#160; &#160; &#160; &#160; var script = document.getElementById(&#34;__ie_onload&#34;);
&#160; &#160; &#160; &#160; &#160; script.onreadystatechange = function() {
&#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2007/04/19/domready/domreadyjpg/' rel='attachment wp-att-107' title='domready.jpg'><img src='http://www.limboy.com/wp-content/uploads/2007/04/domready.jpg' alt='domready.jpg' style="float:left;margin:0 10px 0 0px;" /></a>今天被土豆网的<a href="http://my.opera.com/lexrus/blog/">lex</a>鄙视了，因为我的BLOG在Safari里根本无法浏览——loading永远不会结束，很明显，这意味着webkit引擎不支持<a href="http://www.limboy.com/2007/04/04/theme/">上次提到的</a>判断DOM加载完成的方法。</p>
<p>既然开了新文章，就干脆重新回顾一下这个问题：如今的javascript编程非常依赖DOM（文档对象模型），对HTML和XML来说，DOM是一个应用程序接口 (API) ，对JS来说，DOM为文档创建了程序可以使用的对象和方法，DOM把前端程序和内容结合在一起，就好像ORM（对象-关系映射，比如<a href="http://www.pearchina.com/">PEAR库</a>里的DB_DataObject）把后台程序和关系数据库结合在一起，形象点说它是一颗节点树，没有这棵树的支撑，很多JS方法就无法使用。<span id="more-106"></span></p>
<p>传统方式是通过window.onload事件来判断DOM是否加载完成，但实际上它的加载时间里还包括了img标签插入的图片、FLASH等大家伙，很多时候，来不及等这些东西都下载完成才执行JS（特别是当你要用JS给页面元素注册事件、调整外观，用AJAX加载重要内容）。所以必须有一种方法来单独判断DOM是否加载完成。</p>
<p>国外很早就有强者解决了这个问题，但我上次看的资料其实不完整（不求甚解的下场），最终的解决方案是在几个人的BLOG上讨论出来的……blogsphere（博客圈）果然是一种能激发创造性的社区结构……</p>
<p>首先是<a href="http://dean.edwards.name/weblog/2005/09/busted/">Dean Edwards</a>指出了两件重要的工具：</p>
<ul>
<li>Mozilla提供一个很棒的事件：DOMContentLoaded</li>
<li>微软支持<a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/defer.asp">defer</a>属性，这并不是私有属性，而是包括在W3C的DOM 1标准里的，但是它似乎没有被XHTML支持，还有一个特点是，defer只能放在script标签里，而不能用JS来添加。</li>
</ul>
<p>那么首先在Firefox上判断DOM加载完成就很简单了：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">if</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">addEventListener</span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">addEventListener</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">DOMContentLoaded</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">init</span><span style="color: Gray;">, </span><span style="color: Green;">false</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>Opera9也支持上面的方法，但更低版本就不行了……</p>
<p>至于IE，最早提出的方法是把init函数放在一个单独的ie_onload.js里执行，在HTML调用脚本时加入条件注释和defer：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">&lt;!--[if IE]&gt;&lt;script defer src=&quot;ie_onload.js&quot;&gt;&lt;/script&gt;&lt;![endif]--&gt;</span></li></ol></div>
<p>或者：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">&lt;!--[if IE]&gt;&lt;script defer src=&quot;javascript:'init()'&quot;&gt;&lt;/script&gt;&lt;![endif]--&gt;</span></li></ol></div>
<p>这个方法的缺点是要在HTML里嵌入代码，缺乏灵活性，在<a href="http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited">Matthias Miller</a>加入讨论后，产生了更方便的实现方法：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// for Internet Explorer</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/*@cc_on @*/</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/*@if (@_win32)</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; document.write(&quot;&lt;scr&quot;+&quot;ipt id=__ie_onload defer src=//0&gt;&lt;\/scr&quot;+&quot;ipt&gt;&quot;);</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var script = document.getElementById(&quot;__ie_onload&quot;);</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; script.onreadystatechange = function() {</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (this.readyState == &quot;complete&quot;) {</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init(); // call the onload handler</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; /*@end @*/</span></li></ol></div>
<p>这里的cc就是conditional compilation（条件编译），跟条件注释很像，具体介绍可以看<a href="http://bbs.blueidea.com/redirect.php?tid=2453449&#038;goto=lastpost&#038;highlight=">这里翻译的文章</a>。这里使用CC是因为内部的代码会引起非IE浏览器的错误（比如Safari会出错）</p>
<p>而“script&#8221;被拆成&#8221;scr&#8221;+&#8221;ipt&#8221;似乎是为了避免与诺顿（Norton Internet Security）发生冲突-_____-b</p>
<p>如果你以为这样就可以应付所有情况了，就会像我一样被Safari用户鄙视……</p>
<p>jQuery的创始人John Resig在邮件列表里给出了Safari的解决方法：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// for Safari</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: #8b0000;">/</span><span style="color: Red;">WebKit</span><span style="color: #8b0000;">/i</span><span style="color: Gray;">.</span><span style="color: Blue;">test</span><span style="color: Olive;">(</span><span style="color: Teal;">navigator</span><span style="color: Gray;">.</span><span style="color: Blue;">userAgent</span><span style="color: Olive;">))</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: #ffa500;">// sniff</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_timer</span><span style="color: Gray;"> = </span><span style="color: Blue;">setInterval</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">()</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: #8b0000;">/</span><span style="color: Red;">loaded|complete</span><span style="color: #8b0000;">/</span><span style="color: Gray;">.</span><span style="color: Blue;">test</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">readyState</span><span style="color: Olive;">))</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">init</span><span style="color: Olive;">()</span><span style="color: Gray;">; </span><span style="color: #ffa500;">// call the onload handler</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Maroon;">10</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li></ol></div>
<p>最后有人封装了完整的代码：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">/*</span></li>
<li><span style="color: #ffa500;"> * (c)2006 Dean Edwards/Matthias Miller/John Resig</span></li>
<li><span style="color: #ffa500;"> * Special thanks to Dan Webb's domready.js Prototype extension</span></li>
<li><span style="color: #ffa500;"> * and Simon Willison's addLoadEvent</span></li>
<li><span style="color: #ffa500;"> *</span></li>
<li><span style="color: #ffa500;"> * For more info, see:</span></li>
<li><span style="color: #ffa500;"> * </span><span style="color: Blue;">http://dean.edwards.name/weblog/2006/06/again/</span></li>
<li><span style="color: #ffa500;"> * </span><span style="color: Blue;">http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype</span></li>
<li><span style="color: #ffa500;"> * </span><span style="color: Blue;">http://simon.incutio.com/archive/2004/05/26/addLoadEvent</span></li>
<li><span style="color: #ffa500;"> * </span></li>
<li><span style="color: #ffa500;"> * Thrown together by Jesse Skinner (</span><span style="color: Blue;">http://www.thefutureoftheweb.com/</span><span style="color: #ffa500;">)</span></li>
<li><span style="color: #ffa500;"> *</span></li>
<li><span style="color: #ffa500;"> *</span></li>
<li><span style="color: #ffa500;"> * To use: call addDOMLoadEvent one or more times with functions, ie:</span></li>
<li><span style="color: #ffa500;"> *</span></li>
<li><span style="color: #ffa500;"> *&nbsp; &nbsp; function something() {</span></li>
<li><span style="color: #ffa500;"> *&nbsp; &nbsp; &nbsp;&nbsp; // do something</span></li>
<li><span style="color: #ffa500;"> *&nbsp; &nbsp; }</span></li>
<li><span style="color: #ffa500;"> *&nbsp; &nbsp; addDOMLoadEvent(something);</span></li>
<li><span style="color: #ffa500;"> *</span></li>
<li><span style="color: #ffa500;"> *&nbsp; &nbsp; addDOMLoadEvent(function() {</span></li>
<li><span style="color: #ffa500;"> *&nbsp; &nbsp; &nbsp; &nbsp; // do other stuff</span></li>
<li><span style="color: #ffa500;"> *&nbsp; &nbsp; });</span></li>
<li><span style="color: #ffa500;"> *</span></li>
<li><span style="color: #ffa500;"> */</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">function</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">addDOMLoadEvent</span><span style="color: Olive;">(</span><span style="color: Blue;">func</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Gray;">!</span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_events</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">init</span><span style="color: Gray;"> = </span><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Olive;">()</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// quit if this function has already been called</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Gray;">.</span><span style="color: Blue;">done</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Green;">return</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// flag this function so we don't do the same thing twice</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">arguments</span><span style="color: Gray;">.</span><span style="color: Blue;">callee</span><span style="color: Gray;">.</span><span style="color: Blue;">done</span><span style="color: Gray;"> = </span><span style="color: Green;">true</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// kill the timer</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_timer</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">clearInterval</span><span style="color: Olive;">(</span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_timer</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_timer</span><span style="color: Gray;"> = </span><span style="color: Green;">null</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// execute each function in the stack in the order they were added</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">for</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">i</span><span style="color: Gray;">=</span><span style="color: Maroon;">0</span><span style="color: Gray;">;</span><span style="color: Blue;">i</span><span style="color: Gray;"> &lt; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_events</span><span style="color: Gray;">.</span><span style="color: Blue;">length</span><span style="color: Gray;">;</span><span style="color: Blue;">i</span><span style="color: Gray;">++</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_events</span><span style="color: Olive;">[</span><span style="color: Blue;">i</span><span style="color: Olive;">]()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_events</span><span style="color: Gray;"> = </span><span style="color: Green;">null</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// for Mozilla/Opera9</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">addEventListener</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">addEventListener</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">DOMContentLoaded</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">init</span><span style="color: Gray;">, </span><span style="color: Green;">false</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// for Internet Explorer</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/*@cc_on @*/</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">/*@if (@_win32)</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; document.write(&quot;&lt;scr&quot;+&quot;ipt id=__ie_onload defer src=//0&gt;&lt;\/scr&quot;+&quot;ipt&gt;&quot;);</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var script = document.getElementById(&quot;__ie_onload&quot;);</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; script.onreadystatechange = function() {</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (this.readyState == &quot;complete&quot;) {</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init(); // call the onload handler</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &nbsp; /*@end @*/</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// for Safari</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: #8b0000;">/</span><span style="color: Red;">WebKit</span><span style="color: #8b0000;">/i</span><span style="color: Gray;">.</span><span style="color: Blue;">test</span><span style="color: Olive;">(</span><span style="color: Teal;">navigator</span><span style="color: Gray;">.</span><span style="color: Blue;">userAgent</span><span style="color: Olive;">))</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span><span style="color: Gray;"> </span><span style="color: #ffa500;">// sniff</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_timer</span><span style="color: Gray;"> = </span><span style="color: Blue;">setInterval</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">()</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: #8b0000;">/</span><span style="color: Red;">loaded|complete</span><span style="color: #8b0000;">/</span><span style="color: Gray;">.</span><span style="color: Blue;">test</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">readyState</span><span style="color: Olive;">))</span><span style="color: Gray;"> </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">init</span><span style="color: Olive;">()</span><span style="color: Gray;">; </span><span style="color: #ffa500;">// call the onload handler</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;">, </span><span style="color: Maroon;">10</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// for other browsers</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">onload</span><span style="color: Gray;"> = </span><span style="color: Blue;">init</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: #ffa500;">// create event function stack</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_events</span><span style="color: Gray;"> = </span><span style="color: Olive;">[]</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: #ffa500;">// add function to event stack</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">__load_events</span><span style="color: Gray;">.</span><span style="color: Blue;">push</span><span style="color: Olive;">(</span><span style="color: Blue;">func</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>而且他还结合了<a href="http://simonwillison.net/2004/May/26/addLoadEvent/">addLoadEvent函数</a>，我在上篇文章里有一种往onload里注册新事件的简单方法，是利用JS的特性：“函数是一等公民”，而这里是利用数组来登记所有事件，与<em>Ajax in Action</em>里提到的Observer模式差不多。有了这段代码，只要使用addDOMLoadEvent(函数名)，就可以反复添加事件函数，而不用担心覆盖原来注册的函数。</p>
<p>另外，喜欢用prototype的话，也可以用这个<a href="http://clientside.cnet.com/code-snippets/event-scripting/a-dom-ready-extension-for-prototype/">扩展</a>。</p>
<p>Matthias Miller还提到了<a href="http://www.outofhanwell.com/blog/index.php?title=using_window_onload_over_https&#038;more=1&#038;c=1&#038;tb=1&#038;pb=1">HTTS加密连接的情况</a>。</p>
<p>国外BLOG上的好东西很多，我觉得想解决技术问题，与其买大部头或畅销书啃，不如用好搜索引擎，多在BLOG之间跳转几下，多看看评论，可以学到更多东西。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2007/04/19/domready/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>奇幻大辞典online版完工！</title>
		<link>http://www.limboy.com/2007/04/14/fdict/</link>
		<comments>http://www.limboy.com/2007/04/14/fdict/#comments</comments>
		<pubDate>Fri, 13 Apr 2007 16:20:05 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[D&D]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2007/04/14/%e5%a5%87%e5%b9%bb%e5%a4%a7%e8%be%9e%e5%85%b8online%e7%89%88%e5%8f%91%e5%b8%83%ef%bc%81/</guid>
		<description><![CDATA[A Long Time Ago in a Galaxy Far, Far Away&#8230; Linkcd老爷用FoxPro做了一个辞典软件，虽然没有金山糍粑那样的取词功能，但“奇幻大辞典”拥有专业的奇幻游戏术语词库，成为了广大玩家和苦力翻译们必备的神器，如今回想起来，辞典的最后一次更新居然已经是四年前的事……
时代已经不同了！如今linkcd老爷在惠普搞.net，FoxPro、Delphi这类玩意都早已成为过时的技术，基于Web的应用取代桌面软件成为一种越来越明显的潮流，单机PC游戏陷入低谷，&#8221;online&#8221;的后缀出现在所有经典名词的后面比如魔戒DND科南战锤大航海……其实我想说的就是，奇幻大辞典也与时俱进发布全新的在线版了！
其实这个东西从去年起就挂在NT的服务器里了，最初只有JAY写的一个PHP查询页面，我用AJAX技术重新做了一个华丽（这是重点！）的前端，把PHP页面改写成了“Code Behind”，参考google suggest加入了一些交互功能。因为当时还存在一些BUG和运行效率的问题，不好意思公开。这两天我对代码做了一次重构（说难听一点是“重写”），解决了所有BUG，还加入了键盘操作和缓存机制，感觉已经比较完善了……
永久域名：http://www.limboy.com/project/dict/

在线版的优点也很明显：不需要事先安装，不需要同步数据库。由于时间有限，目前暂时还没有添加新词汇、修改词汇信息和分类查询的功能，以后会根据需要添加。
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2007/04/fd1.jpg' title='fd1.jpg'><img src='http://www.limboy.com/wp-content/uploads/2007/04/fd1.jpg' alt='fd1.jpg' style="float:left;margin:0 10px 0 0px;" /></a>A Long Time Ago in a Galaxy Far, Far Away&#8230; <a href="http://www.cnblogs.com/linkcd/">Linkcd老爷</a>用FoxPro做了一个辞典软件，虽然没有金山糍粑那样的取词功能，但“奇幻大辞典”拥有专业的奇幻游戏术语词库，成为了广大玩家和苦力翻译们必备的神器，如今回想起来，辞典的最后一次更新居然已经是四年前的事……</p>
<p>时代已经不同了！如今linkcd老爷在惠普搞.net，FoxPro、Delphi这类玩意都早已成为过时的技术，基于Web的应用取代桌面软件成为一种越来越明显的潮流，单机PC游戏陷入低谷，&#8221;online&#8221;的后缀出现在所有经典名词的后面比如魔戒DND科南战锤大航海……其实我想说的就是，奇幻大辞典也与时俱进发布全新的<a href="http://www.limboy.com/project/dict/">在线版</a>了！<span id="more-102"></span></p>
<p>其实这个东西从去年起就挂在NT的服务器里了，最初只有JAY写的一个PHP查询页面，我用AJAX技术重新做了一个华丽（这是重点！）的前端，把PHP页面改写成了“Code Behind”，参考<a href="http://www.google.com/webhp?complete=1&amp;hl=en">google suggest</a>加入了一些交互功能。因为当时还存在一些BUG和运行效率的问题，不好意思公开。这两天我对代码做了一次重构（说难听一点是“重写”），解决了所有BUG，还加入了键盘操作和缓存机制，感觉已经比较完善了……</p>
<p>永久域名：<a href="http://www.limboy.com/project/dict/">http://www.limboy.com/project/dict/</a></p>
<p><a href='http://www.limboy.com/wp-content/uploads/2007/04/sshot.jpg' title='fdshot'><img src='http://www.limboy.com/wp-content/uploads/2007/04/sshot.thumbnail.jpg' alt='fdshot' /></a></p>
<p>在线版的优点也很明显：不需要事先安装，不需要同步数据库。由于时间有限，目前暂时还没有添加新词汇、修改词汇信息和分类查询的功能，以后会根据需要添加。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2007/04/14/fdict/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>YY专用Wordpress主题终于完成了……</title>
		<link>http://www.limboy.com/2007/04/04/theme/</link>
		<comments>http://www.limboy.com/2007/04/04/theme/#comments</comments>
		<pubDate>Wed, 04 Apr 2007 07:43:53 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Blogger]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[用户体验]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2007/04/04/theme/</guid>
		<description><![CDATA[上次Blogger被GFWED的时候，我说过坚决不转移到WORDPRESS是因为它太迎合我把东西做复杂的欲望，现在实践证明确实如此……
由于形势所迫（不仅因为GFW），我不得不放弃Blogger重新建立一个稳定的BLOG，熟悉WP的插件加上制作这个主题花了4天时间，超乎想象了……时间主要浪费在设计、浏览器兼容上面……本帖我将用来发牢骚，并且分享一些经验教训，没兴趣的同学可以跳转到其他地方去了……
页面设计在中途大幅度修改了3次，这次我想恢复到传统风格，因为如今那种简洁大字体大空白色彩明亮固定宽度居中对齐边缘有阴影的WEB2.0风格太普遍了，作为代表个人形象的BLOG，我希望有一些不同的个性，而且我虽然也喜欢“简洁”，但不喜欢“简单”。本来是想把WEB2.0的设计元素和配色与奇幻游戏元素结合在一起，但尝试过之后发现很困难，主要是配色很难，而且“留白”在WEB2.0风格里确实占很重要的地位，但在这个页面里我没办法留很多空白（何况最初就决定要做三栏布局）。与做图和配色相比，我还是更喜欢写代码，所以我懒得花更多时间来完善目前的设计了……
这个BLOG的布局可以说是实验风格的……三栏的液态布局，左栏的宽度是自适应的，还有一部分内容固定在窗口顶部，无论怎样拖滚动条，它都会随着页面移动，实际上我是受了Westeros的启发才想用这种相对窗口固定的设计，但是实现起来很麻烦（Westeros的效果其实也只支持IE7和FIREFOX，在IE6里会变得像框架布局一样），如果用JS来实现，移动就不可能是平滑的，衔接的效果不好，用CSS来实现却有很严重的缺陷，首先IE7以下版本的浏览器不支持position:fixed属性，必须用HACK来模拟，我采用的方法是用一个DIV来包含所有元素，在IE7以下版本里给它height:100%;overflow-y:auto;的属性，把顶部元素的定位改成绝对，所以IE6用户看到的右侧滚动条其实不是浏览器本身的……
由于用了两种布局方式，而液态布局的三栏里既有浮动也有非浮动，再加上中间的羊皮纸效果必须在左右边缘采用不同的背景图，很多地方的定位都要精确到像素……所以这个主题的CSS写起来很头疼，DEBUG花了很多时间，目前在opera里似乎还有一个毛病，但我一向都是歧视opera用户的（因为占有率才0.8%左右嘛），暂时懒得改了……
由于设计上的限制，有2个地方的布局不得不用JS来调整，一个是改变顶部fixed层的宽度，因为它的定位方式是fixed或absolute，无法做出液态的宽度（也就是说宽度随浏览器的大小自动填充，但是与右侧总保持固定距离），另一个是让左栏和中栏的高度相等，由于无法使用统一的背景图片，所以这里也只能用JS来调整……
我倒不在意什么“预留退路”、“无障碍”之类的JS设计观念，反正如今在WEB上混没有JS已经寸步难行了，而且我没有用JS来影响内容…………但是用JS来调整布局会遇到另一个问题，如今的JS代码都是放在window.onload里运行的，因为页面加载完成、DOM建立之前，很多方法都不能用，但问题在于，window.onload不仅要等DOM加载完，还要等图片（指img标签）加载完，我的BLOG页面里整合了很多东西，每篇文章的题图、YUPOO的相册、豆瓣的封面……如果要等这些东西都加载完才修正布局，显然是不现实的，幸好我在国外一个BLOG上找到解决办法（地址忘记了，抱歉），可以在onload事件触发之前、DOM刚加载完时就执行修正布局的函数：
// for Mozilla DOM onloaded
if&#160;(document.addEventListener)&#160;
{
&#160; &#160; document.addEventListener(&#34;DOMContentLoaded&#34;, DOMsinit, null);
}
DOMsinit就是我要执行的函数，第三个参数本来是布尔值，用来决定事件在冒泡还是捕获阶段触发，但DOM加载的事件显然没这些东西，所以必须传空值，以上是适合标准兼容浏览器的方法，对IE要用完全不同的代码（放在HTML里）：
&#60;!--[if IE]&#62;
&#160; &#160; &#60;script defer src=&#34;&#60;?php bloginfo('stylesheet_directory'); ?&#62;/js/ie_onload.js&#34; type=&#34;text/javascript&#34;&#62;&#60;/script&#62;
&#60;![endif]--&#62;
ie_onload.js就是要执行的函数……为了IE要专门增添一个JS文件，真是麻烦……我还没搞清除defer是什么鬼东西，反正这样用就没错了……
就算你只是使用window.onload，也要考虑到：WP本身和某些插件，都可能有自己的JS函数，会用到window.onload，如果你直接写window.onload=function(){&#8230;&#8230;..}，就会把其他功能覆盖掉，一定要用这类方法：
if ( typeof window.onload!='function')
{
&#160; &#160; window.onload=function()
&#160; &#160; {
&#160; &#160; &#160; &#160; yysinit();&#160;&#160; //页面加载完成时调用的函数
&#160; &#160; }
}
else
{
&#160; &#160; var&#160;oldonload=window.onload;
&#160; &#160; window.onload=function()
&#160; &#160; {
&#160; &#160; &#160; &#160; oldonload();
&#160; &#160; &#160; &#160; yysinit();&#160; &#160; //页面加载完成时调用的函数
&#160; &#160; }
}
本来我还希望用户在改变浏览器窗口大小后，顶部的宽度也能跟着调整（因为用CSS实现的自适应都有这种效果），所以用了window.onresize事件，但大家都知道，即使是液态布局，当窗口小于一定宽度后，布局也会乱掉，因为容器虽然可以自动变形，但内容却不会改变，浮动定位在这方面最敏感……由于我的BLOG页面里内容比较多，所以宽度不能少于900多px，在window.onresize里我也做了相应的处理，但是问题就出来了……这个该死的事件在不同浏览器里的行为不一致，在按住窗口边框——拖动——放开鼠标的操作之后，onresize在firefox里会触发1次，在IE7里会触发2次，而在IE6里……居然触发3次&#8230;&#8230;结果就是：限制最小宽度的函数在IE6里会导致浏览器假死……我觉得没必要为这种BUG自找麻烦，所以把onresize改成这样了：
window.onresize=function(){
&#160; &#160; var&#160;aVersion=navigator.appVersion;
&#160; &#160; var&#160;version=parseInt(aVersion.split(&#34;MSIE&#34;)[1]);
&#160; &#160; 
&#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2007/04/wp.jpg' title='mytheme'><img src='http://www.limboy.com/wp-content/uploads/2007/04/wp.thumbnail.jpg' alt='mytheme' style="float:left;margin:0 10px 0 0px;" /></a>上次Blogger被GFWED的时候，我说过坚决不转移到WORDPRESS是因为<a href="http://www.limboy.com/2006/12/03/continue/">它太迎合我把东西做复杂的欲望</a>，现在实践证明确实如此……</p>
<p>由于形势所迫（不仅因为GFW），我不得不放弃Blogger重新建立一个稳定的BLOG，熟悉WP的插件加上制作这个主题花了4天时间，超乎想象了……时间主要浪费在设计、浏览器兼容上面……本帖我将用来发牢骚，并且分享一些经验教训，没兴趣的同学可以跳转到其他地方去了……<span id="more-100"></span></p>
<p>页面设计在中途大幅度修改了3次，这次我想恢复到传统风格，因为如今那种简洁大字体大空白色彩明亮固定宽度居中对齐边缘有阴影的WEB2.0风格太普遍了，作为代表个人形象的BLOG，我希望有一些不同的个性，而且我虽然也喜欢“简洁”，但不喜欢“简单”。本来是想把WEB2.0的设计元素和配色与奇幻游戏元素结合在一起，但尝试过之后发现很困难，主要是配色很难，而且“留白”在WEB2.0风格里确实占很重要的地位，但在这个页面里我没办法留很多空白（何况最初就决定要做三栏布局）。与做图和配色相比，我还是更喜欢写代码，所以我懒得花更多时间来完善目前的设计了……</p>
<p>这个BLOG的布局可以说是实验风格的……三栏的液态布局，左栏的宽度是自适应的，还有一部分内容固定在窗口顶部，无论怎样拖滚动条，它都会随着页面移动，实际上我是受了<a href="http://www.westeros.org/About/">Westeros</a>的启发才想用这种相对窗口固定的设计，但是实现起来很麻烦（Westeros的效果其实也只支持IE7和FIREFOX，在IE6里会变得像框架布局一样），如果用JS来实现，移动就不可能是平滑的，衔接的效果不好，用CSS来实现却有很严重的缺陷，首先IE7以下版本的浏览器不支持position:fixed属性，必须用HACK来模拟，我采用的方法是用一个DIV来包含所有元素，在IE7以下版本里给它height:100%;overflow-y:auto;的属性，把顶部元素的定位改成绝对，所以IE6用户看到的右侧滚动条其实不是浏览器本身的……</p>
<p>由于用了两种布局方式，而液态布局的三栏里既有浮动也有非浮动，再加上中间的羊皮纸效果必须在左右边缘采用不同的背景图，很多地方的定位都要精确到像素……所以这个主题的CSS写起来很头疼，DEBUG花了很多时间，目前在opera里似乎还有一个毛病，但我一向都是歧视opera用户的（因为占有率才0.8%左右嘛），暂时懒得改了……</p>
<p>由于设计上的限制，有2个地方的布局不得不用JS来调整，一个是改变顶部fixed层的宽度，因为它的定位方式是fixed或absolute，无法做出液态的宽度（也就是说宽度随浏览器的大小自动填充，但是与右侧总保持固定距离），另一个是让左栏和中栏的高度相等，由于无法使用统一的背景图片，所以这里也只能用JS来调整……</p>
<p>我倒不在意什么“预留退路”、<a href="http://realazy.org/blog/2007/01/01/ppk-on-javascript-study-note-part02-3/">“无障碍”</a>之类的JS设计观念，反正如今在WEB上混没有JS已经寸步难行了，而且我没有用JS来影响内容…………但是用JS来调整布局会遇到另一个问题，如今的JS代码都是放在window.onload里运行的，因为页面加载完成、DOM建立之前，很多方法都不能用，但问题在于，window.onload不仅要等DOM加载完，还要等图片（指img标签）加载完，我的BLOG页面里整合了很多东西，每篇文章的题图、YUPOO的相册、豆瓣的封面……如果要等这些东西都加载完才修正布局，显然是不现实的，幸好我在国外一个BLOG上找到解决办法（地址忘记了，抱歉），可以在onload事件触发之前、DOM刚加载完时就执行修正布局的函数：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">// for Mozilla DOM onloaded</span></li>
<li><span style="color: Green;">if</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">addEventListener</span><span style="color: Olive;">)</span><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">addEventListener</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">DOMContentLoaded</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Blue;">DOMsinit</span><span style="color: Gray;">, </span><span style="color: Green;">null</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>DOMsinit就是我要执行的函数，第三个参数本来是布尔值，用来决定事件在冒泡还是捕获阶段触发，但DOM加载的事件显然没这些东西，所以必须传空值，以上是适合标准兼容浏览器的方法，对IE要用完全不同的代码（放在HTML里）：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">&lt;!--[if IE]&gt;</span></li>
<li><span style="color: #ffa500;">&nbsp; &nbsp; &lt;script defer src=&quot;&lt;?php bloginfo('stylesheet_directory'); ?&gt;/js/ie_onload.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</span></li>
<li><span style="color: #ffa500;">&lt;![endif]--&gt;</span></li></ol></div>
<p>ie_onload.js就是要执行的函数……为了IE要专门增添一个JS文件，真是麻烦……我还没搞清除defer是什么鬼东西，反正这样用就没错了……</p>
<p>就算你只是使用window.onload，也要考虑到：WP本身和某些插件，都可能有自己的JS函数，会用到window.onload，如果你直接写window.onload=function(){&#8230;&#8230;..}，就会把其他功能覆盖掉，一定要用这类方法：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">if</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: Gray;"> </span><span style="color: Green;">typeof</span><span style="color: Gray;"> </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">onload</span><span style="color: Gray;">!=</span><span style="color: #8b0000;">'</span><span style="color: Red;">function</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">onload</span><span style="color: Gray;">=</span><span style="color: Green;">function</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">yysinit</span><span style="color: Olive;">()</span><span style="color: Gray;">;&nbsp;&nbsp; </span><span style="color: #ffa500;">//页面加载完成时调用的函数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Green;">else</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">oldonload</span><span style="color: Gray;">=</span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">onload</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">onload</span><span style="color: Gray;">=</span><span style="color: Green;">function</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">oldonload</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Blue;">yysinit</span><span style="color: Olive;">()</span><span style="color: Gray;">;&nbsp; &nbsp; </span><span style="color: #ffa500;">//页面加载完成时调用的函数</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>本来我还希望用户在改变浏览器窗口大小后，顶部的宽度也能跟着调整（因为用CSS实现的自适应都有这种效果），所以用了window.onresize事件，但大家都知道，即使是液态布局，当窗口小于一定宽度后，布局也会乱掉，因为容器虽然可以自动变形，但内容却不会改变，浮动定位在这方面最敏感……由于我的BLOG页面里内容比较多，所以宽度不能少于900多px，在window.onresize里我也做了相应的处理，但是问题就出来了……这个该死的事件在不同浏览器里的行为不一致，在按住窗口边框——拖动——放开鼠标的操作之后，onresize在firefox里会触发1次，在IE7里会触发2次，而在IE6里……居然触发3次&#8230;&#8230;结果就是：限制最小宽度的函数在IE6里会导致浏览器假死……我觉得没必要为这种BUG自找麻烦，所以把onresize改成这样了：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">onresize</span><span style="color: Gray;">=</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">aVersion</span><span style="color: Gray;">=</span><span style="color: Teal;">navigator</span><span style="color: Gray;">.</span><span style="color: Blue;">appVersion</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">version</span><span style="color: Gray;">=</span><span style="color: Blue;">parseInt</span><span style="color: Olive;">(</span><span style="color: Blue;">aVersion</span><span style="color: Gray;">.</span><span style="color: Blue;">split</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">MSIE</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)[</span><span style="color: Maroon;">1</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">body</span><span style="color: Gray;">.</span><span style="color: Blue;">offsetWidth</span><span style="color: Gray;">&lt;</span><span style="color: Maroon;">941</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Blue;">version</span><span style="color: Gray;">&gt;=</span><span style="color: Maroon;">7</span><span style="color: Gray;"> || </span><span style="color: Blue;">aVersion</span><span style="color: Gray;">.</span><span style="color: Blue;">indexOf</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">MSIE</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">==-</span><span style="color: Maroon;">1</span><span style="color: Olive;">)</span><span style="color: Blue;">getid</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">outwrapper</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">width</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">942px</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Green;">else</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Blue;">version</span><span style="color: Gray;">&gt;=</span><span style="color: Maroon;">7</span><span style="color: Gray;"> || </span><span style="color: Blue;">aVersion</span><span style="color: Gray;">.</span><span style="color: Blue;">indexOf</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">MSIE</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">==-</span><span style="color: Maroon;">1</span><span style="color: Olive;">)</span><span style="color: Blue;">getid</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">outwrapper</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">width</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span></li>
<li><span style="color: Gray;">&nbsp; &nbsp; </span><span style="color: Blue;">getid</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">top</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">width</span><span style="color: Gray;">=</span><span style="color: Blue;">getid</span><span style="color: Olive;">(</span><span style="color: #8b0000;">'</span><span style="color: Red;">sidebar-1</span><span style="color: #8b0000;">'</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: Blue;">offsetLeft</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">px</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">}</span></li></ol></div>
<p>version>=7 和 aVersion.indexOf(&#8220;MSIE&#8221;)==-1 都是浏览器校验，表示只有当IE版本大于或等于7，或者在非IE浏览器里，才限制页面的最小宽度……</p>
<p>本来还想加一些JS效果，比如可折叠的侧栏widget之类，但是把兼容性改下来之后就完全没心情了………………</p>
<p>最后还是回到设计话题，自适应宽度的布局其实还是比较迎合大屏幕（高分辨率），可以充分利用空间，改善用户体验，但是如果页面里内容比较紧凑，那么对于普通分辨率的用户（1024×768）来说，效果反而不如固定宽度……目前主流的BLOG设计是固定宽度，单栏或两栏，底部再加上一栏放各种列表，所以我的布局方法虽然技术上麻烦的多，但也许并不讨好，那也没办法的事……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2007/04/04/theme/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>新作品：可以自由编辑的Google地图，700行javascript+70行php</title>
		<link>http://www.limboy.com/2007/03/13/mapfolio/</link>
		<comments>http://www.limboy.com/2007/03/13/mapfolio/#comments</comments>
		<pubDate>Tue, 13 Mar 2007 10:20:23 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[web服务/应用]]></category>

		<guid isPermaLink="false">http://localhost/wordpress/?p=15</guid>
		<description><![CDATA[以前在龙骑士城堡提过一种想法，就是用GOOGLE MAPS来做桌面游戏玩家的主题地图。当时推荐的是EEMAP的服务，然则这个网站的注册一直需要邀请码，很不方便，而且界面难看，速度也很慢……
当时就想过自己来做一个GOOGLE MAPS API的应用，但一直没时间看API文档。这几天总算有空闲（辞职就是好哑），把想象中的东西基本上做出来了，我把它叫作Free Map Folio v1.0（取自DND设定集的名字），可以像维基百科那样自由编辑，前端是静态的HTML，数据库用xml，方便部署，而交互操作的程序完全用Javascirpt来写，只需要打开一个HTML页面，然后整个使用过程都不需要刷新页面，也不需要从外部获取数据（只用AJAX提交数据）。
实际应用：桌面游戏玩家主题地图（乱加东西要记得删掉）——http://www.ntrpg.org/yy/maps/
演示地址(上面的镜像)：http://www.limboy.com/project/maps/



Javascirpt的主要代码有700行，都写在一个对象里(yymap)，我本来想把每个单独的功能都封装起来，避免重复代码（DRY原则？），不过后来页面右侧栏加入了“地点列表”之后，程序就改复杂了……………以后有空要做一下重构……
用户只需要访问一个静态的HTML页面，唯一一次从外部获取数据是在地图加载的时候，用了API提供的XmlHttpRequest对象，非常方便，比如GXml.parse可以把responseText获得的文本转换成XML DOM。不过用GXmlHttp和GDownloadUrl的时候，IE7都会遇到一个缓存问题（IE6没试过）：刷新页面后，不会重新下载XML文件，因此页面上的数据不会更新。解决方法是在xml文件的地址后面加随机参数（感谢tinyfool的帮助）：
var ramnum = parseInt(100000*Math.random());var request = GXmlHttp.create();
&#160;
request.open(&#34;GET&#34;, &#34;db.xml?x=&#34;+ramnum, true);
标记（Marker）的样式可以自定义，所以我做了一个选择图标的功能，先建立所有图标的基本属性（yymap.baseIcon），包括阴影图片和各种尺寸，然后在创建新标记时，根据用户选择的图标，把地址传给icon.image就行了。其实还可以做一个自定义图片的功能，允许用户在编辑器里上传自己的图片（比如照片）当作图标，只是必须把图片处理成固定大小的32位PNG……
点击标记弹出的信息窗口是最麻烦的东西，因为页面里同时只能存在一个信息窗口，而信息窗口里的内容也不能保存在标记的对象里，所以要修改某个标记对应的信息窗内容，就只能修改它的点击事件：
GEvent.addListener(marker, &#34;click&#34;, function(){
&#160;
yymap.whenClickMarker(marker,info,point,icon.image);
&#160;
});
我在点击事件里传了4个参数：点击的标记对象 , 信息窗的内容, 标记的经纬度, 标记使用的图标， 除了用来显示信息窗，也是为了把它们传给全局变量（因为编辑这个标记的时候会用到）。
为了让右侧栏列表与地图上的图标一一对应，我在列表的每个链接上设了跟标记对应的ID，每次做添加、编辑或删除的操作时，除了修改标记本身的点击事件，还要用ID找到列表上对应的链接，修改链接的点击事件…………总之，感觉这个侧栏列表很添乱……却又是必要的功能……
在我写这篇文章时，还有一个搜索地名的功能没做好。本来API提供了地理译码的功能，可以把符合格式的地名转换成JSON数据（用JS对象来传递数据的格式），但这么方便的东西我却享受不了——地理译码还没有支持中国的地名…………在地图上就能很明显的看到：周围日本、印度，都有详细的城市名字，放大后还有交通信息，而中国是一片空白…………
因此对于不熟悉地理的用户来说，要在这样的中国地图上找到某个城市可能太难了，搜索地名是必须的功能。由于没有地理译码，目前使用GOOGLE MAPS API的网站，比如EEMAP，都是自己建立地名和经纬度对应的数据库。我找到了一个很全的“乡镇级中国行政区划地标”，是GOOGLE EARTH用的KMZ文件，但其实就是压缩过的XML，用WINRAR打开就能看到一个KML文件，可以直接拿来当搜索数据库。我考虑过两种实现方法：把用户输入的中文地名用AJAX发给PHP，让PHP搜索这个XML文件里匹配的标签，然后返回相应的经纬度；或者直接用GXmlHttp下载XML，然后用JS的DOM方法来搜索相应的标签，第二种方法很合我的胃口，不需要借道PHP，遗憾的是…………这意味着搜索时要用AJAX获得19M的XML数据……
更新：地名搜索已经完成了，模糊搜索范围包括省会、地级市、县城、村镇……足行匹配，搜索对象在KML文件里排名越靠后，搜索时间越长，不过最多应该不超过5秒……
我刚才测试了一下，搜索不到结果时4.36s，搜索最后一个地名“番阳”需要4.02s，搜索北京1.16s，搜索克拉玛依只需要华丽的328ms
php是由以前的同事Skylin帮忙写的，由于PHP只负责根据AJAX提交的数据，修改XML文件，所以内容很少……然则Skylin不肯用PHP5自带的XML类，而是自己写正则……最后代码只有几十行……果然是高手风范……
比如，这是remove.php:
&#60;?php
&#160;
include&#160;&#34;./globals.php&#34;;
&#160;
$file_content = join('',file(&#34;../db.xml&#34;));if(preg_match(&#34;/&#60;marker&#62;rn&#60;id&#62;&#34;.intval($_POST['id']).&#34;&#60;/id&#62;.*&#60;/marker&#62;rnrn/isU&#34;,$file_content,$array))
&#160;
{
&#160;
$file_content = str_replace($array[0],'',$file_content);
&#160;
}
&#160;
$fp = fopen(&#34;../db.xml&#34;,&#34;w+&#34;);
&#160;
flock($fp,LOCK_EX);
&#160;
fputs($fp,$file_content);
&#160;
flock($fp,LOCK_UN);
&#160;
fclose($fp);
&#160;
?&#62;
不过正则也容易出现问题，例如：在我最初做的XML数据库里面，标签的前面都有缩进，大概因为有的缩进是TAB，有的是空格，导致正则一直出错，只好把XML里的缩进全部删掉了……
目前已经全部完工，可能还有一些小BUG需要修改，比如：在简介里输入全角字符（比如·和——），会导致后面的字符都无法保存。P.S. 单引号、双引号和&#8221;&#38;&#8221;容易引起JS错误，我把它们都屏蔽了-_____-b
]]></description>
			<content:encoded><![CDATA[<p><a href="http://picasaweb.google.com/dexter.yy/BLOG/photo#5048726806888874194"><img src="http://lh3.google.com/image/dexter.yy/RhCuSBSagNI/AAAAAAAAAEw/L9rGLEK-8Ws/s288/map.jpg" style="float:left;margin:0px 10px 5px 0px;width:180px;" /></a>以前在龙骑士城堡<a href="http://www.cndkc.net/bbs/read-htm-tid-26098-keyword-.html" target="_blank">提过一种想法</a>，就是用GOOGLE MAPS来做桌面游戏玩家的主题地图。当时推荐的是<a href="http://www.eemap.org/map/247" target="_blank">EEMAP</a>的服务，然则这个网站的注册一直需要邀请码，很不方便，而且界面难看，速度也很慢……</p>
<p>当时就想过自己来做一个GOOGLE MAPS API的应用，但一直没时间看<a href="http://www.zmap.org/doc/maps/documentation/">API文档</a>。这几天总算有空闲（辞职就是好哑），把想象中的东西基本上做出来了，我把它叫作Free Map Folio v1.0（取自<a href="http://www.wizards.com/default.asp?x=products/dndacc/886480000">DND设定集</a>的名字），可以像维基百科那样自由编辑，前端是静态的HTML，数据库用xml，方便部署，而交互操作的程序完全用Javascirpt来写<span id="more-15"></span>，只需要打开一个HTML页面，然后整个使用过程都不需要刷新页面，也不需要从外部获取数据（只用AJAX提交数据）。</p>
<p>实际应用：桌面游戏玩家主题地图（乱加东西要记得删掉）——<a href="http://www.ntrpg.org/yy/maps/">http://www.ntrpg.org/yy/maps/</a><br />
演示地址(上面的镜像)：<a href="http://www.limboy.com/project/maps/">http://www.limboy.com/project/maps/</a></p>
<p><br/><br />
<a href="http://www.yupoo.com/photos/view?id=ff808081114495c301114a33155e49ce" tip="来YUPOO看我的照片"><img src="http://photo1.yupoo.com/20070313/152852_206019246.jpg" alt="新作品-HTML+PHP+XML轻量级维基地图-2" border="0" height="262" width="420" /></a></p>
<p><a href="http://www.yupoo.com/photos/view?id=ff808081114495c301114a330a1549cc" tip="来YUPOO看我的照片"><img src="http://photo1.yupoo.com/20070313/152849_1838550568.jpg" alt="新作品-HTML+PHP+XML轻量级维基地图-1" border="0" height="262" width="420" /></a></p>
<p>Javascirpt的<a href="http://www.ntrpg.org/yy/maps/js/main.js">主要代码</a>有700行，都写在一个对象里(yymap)，我本来想把每个单独的功能都封装起来，避免重复代码（DRY原则？），不过后来页面右侧栏加入了“地点列表”之后，程序就改复杂了……………以后有空要做一下重构……</p>
<p>用户只需要访问一个静态的HTML页面，唯一一次从外部获取数据是在地图加载的时候，用了API提供的<a href="http://www.zmap.org/doc/maps/documentation/#XML_and_RPC_overview">XmlHttpRequest对象</a>，非常方便，比如<a href="http://www.zmap.org/doc/maps/documentation/reference.html#GXml" target="_blank">GXml.parse</a>可以把responseText获得的文本转换成XML DOM。不过用GXmlHttp和GDownloadUrl的时候，IE7都会遇到一个缓存问题（IE6没试过）：刷新页面后，不会重新下载XML文件，因此页面上的数据不会更新。解决方法是在xml文件的地址后面加随机参数（感谢<a href="http://blog.donews.com/tinyfool/">tinyfool</a>的帮助）：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">ramnum</span><span style="color: Gray;"> = </span><span style="color: Blue;">parseInt</span><span style="color: Olive;">(</span><span style="color: Maroon;">100000</span><span style="color: Gray;">*</span><span style="color: Teal;">Math</span><span style="color: Gray;">.</span><span style="color: Blue;">random</span><span style="color: Olive;">())</span><span style="color: Gray;">;</span><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">request</span><span style="color: Gray;"> = </span><span style="color: Blue;">GXmlHttp</span><span style="color: Gray;">.</span><span style="color: Blue;">create</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">request</span><span style="color: Gray;">.</span><span style="color: Blue;">open</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">GET</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">db.xml?x=</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">+</span><span style="color: Blue;">ramnum</span><span style="color: Gray;">, </span><span style="color: Green;">true</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li></ol></div>
<p>标记（Marker）的样式可以自定义，所以我做了一个选择图标的功能，先建立所有图标的基本属性（yymap.baseIcon），包括阴影图片和各种尺寸，然后在创建新标记时，根据用户选择的图标，把地址传给icon.image就行了。其实还可以做一个自定义图片的功能，允许用户在编辑器里上传自己的图片（比如照片）当作图标，只是必须把图片处理成固定大小的32位PNG……</p>
<p>点击标记弹出的信息窗口是最麻烦的东西，因为页面里同时只能存在一个信息窗口，而信息窗口里的内容也不能保存在标记的对象里，所以要修改某个标记对应的信息窗内容，就只能修改它的点击事件：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">GEvent</span><span style="color: Gray;">.</span><span style="color: Blue;">addListener</span><span style="color: Olive;">(</span><span style="color: Blue;">marker</span><span style="color: Gray;">, </span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">click</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">, </span><span style="color: Green;">function</span><span style="color: Olive;">(){</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">yymap</span><span style="color: Gray;">.</span><span style="color: Blue;">whenClickMarker</span><span style="color: Olive;">(</span><span style="color: Blue;">marker</span><span style="color: Gray;">,</span><span style="color: Blue;">info</span><span style="color: Gray;">,</span><span style="color: Blue;">point</span><span style="color: Gray;">,</span><span style="color: Blue;">icon</span><span style="color: Gray;">.</span><span style="color: Blue;">image</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">})</span><span style="color: Gray;">;</span></li></ol></div>
<p>我在点击事件里传了4个参数：点击的标记对象 , 信息窗的内容, 标记的经纬度, 标记使用的图标， 除了用来显示信息窗，也是为了把它们传给全局变量（因为编辑这个标记的时候会用到）。</p>
<p>为了让右侧栏列表与地图上的图标一一对应，我在列表的每个链接上设了跟标记对应的ID，每次做添加、编辑或删除的操作时，除了修改标记本身的点击事件，还要用ID找到列表上对应的链接，修改链接的点击事件…………总之，感觉这个侧栏列表很添乱……却又是必要的功能……</p>
<p>在我写这篇文章时，还有一个搜索地名的功能没做好。本来API提供了<a href="http://www.zmap.org/doc/maps/documentation/#Geocoding_JavaScript">地理译码</a>的功能，可以把符合格式的地名转换成JSON数据（用JS对象来传递数据的格式），但这么方便的东西我却享受不了——地理译码还没有支持中国的地名…………在地图上就能很明显的看到：周围日本、印度，都有详细的城市名字，放大后还有交通信息，而中国是一片空白…………</p>
<p>因此对于不熟悉地理的用户来说，要在这样的中国地图上找到某个城市可能太难了，搜索地名是必须的功能。由于没有地理译码，目前使用GOOGLE MAPS API的网站，比如EEMAP，都是自己建立地名和经纬度对应的数据库。我找到了一个很全的“<a href="http://bbs.godeyes.cn/Announce/Announce.asp?BoardID=100&amp;ID=77707">乡镇级中国行政区划地标</a>”，是GOOGLE EARTH用的KMZ文件，但其实就是压缩过的XML，用WINRAR打开就能看到一个KML文件，可以直接拿来当搜索数据库。我考虑过两种实现方法：把用户输入的中文地名用AJAX发给PHP，让PHP搜索这个XML文件里匹配的标签，然后返回相应的经纬度；或者直接用GXmlHttp下载XML，然后用JS的DOM方法来搜索相应的标签，第二种方法很合我的胃口，不需要借道PHP，遗憾的是…………这意味着搜索时要用AJAX获得19M的XML数据……</p>
<blockquote><p>更新：地名搜索已经完成了，模糊搜索范围包括省会、地级市、县城、村镇……足行匹配，搜索对象在KML文件里排名越靠后，搜索时间越长，不过最多应该不超过5秒……</p>
<p>我刚才测试了一下，搜索不到结果时4.36s，搜索最后一个地名“番阳”需要4.02s，搜索北京1.16s，搜索克拉玛依只需要华丽的328ms</p></blockquote>
<p>php是由以前的同事Skylin帮忙写的，由于PHP只负责根据AJAX提交的数据，修改XML文件，所以内容很少……然则Skylin不肯用PHP5自带的XML类，而是自己写正则……最后代码只有几十行……果然是高手风范……</p>
<p>比如，这是remove.php:</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">&lt;?php</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">include</span><span style="color: Gray;">&nbsp;</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">./globals.php</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #00008b;">$file_content</span><span style="color: Gray;"> = </span><span style="color: Blue;">join</span><span style="color: Olive;">(</span><span style="color: #8b0000;">''</span><span style="color: Gray;">,</span><span style="color: Blue;">file</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">../db.xml</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">))</span><span style="color: Gray;">;</span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Blue;">preg_match</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">/&lt;marker&gt;rn&lt;id&gt;</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">.</span><span style="color: Blue;">intval</span><span style="color: Olive;">(</span><span style="color: #00008b;">$_POST</span><span style="color: Olive;">[</span><span style="color: #8b0000;">'</span><span style="color: Red;">id</span><span style="color: #8b0000;">'</span><span style="color: Olive;">])</span><span style="color: Gray;">.</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">&lt;/id&gt;.*&lt;/marker&gt;rnrn/isU</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">,</span><span style="color: #00008b;">$file_content</span><span style="color: Gray;">,</span><span style="color: #00008b;">$array</span><span style="color: Olive;">))</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #00008b;">$file_content</span><span style="color: Gray;"> = </span><span style="color: Blue;">str_replace</span><span style="color: Olive;">(</span><span style="color: #00008b;">$array</span><span style="color: Olive;">[</span><span style="color: Maroon;">0</span><span style="color: Olive;">]</span><span style="color: Gray;">,</span><span style="color: #8b0000;">''</span><span style="color: Gray;">,</span><span style="color: #00008b;">$file_content</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: #00008b;">$fp</span><span style="color: Gray;"> = </span><span style="color: Blue;">fopen</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">../db.xml</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">,</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">w+</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">flock</span><span style="color: Olive;">(</span><span style="color: #00008b;">$fp</span><span style="color: Gray;">,</span><span style="color: Blue;">LOCK_EX</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">fputs</span><span style="color: Olive;">(</span><span style="color: #00008b;">$fp</span><span style="color: Gray;">,</span><span style="color: #00008b;">$file_content</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">flock</span><span style="color: Olive;">(</span><span style="color: #00008b;">$fp</span><span style="color: Gray;">,</span><span style="color: Blue;">LOCK_UN</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">fclose</span><span style="color: Olive;">(</span><span style="color: #00008b;">$fp</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">?&gt;</span></li></ol></div>
<p>不过正则也容易出现问题，例如：在我最初做的XML数据库里面，标签的前面都有缩进，大概因为有的缩进是TAB，有的是空格，导致正则一直出错，只好把XML里的缩进全部删掉了……</p>
<p>目前已经全部完工，可能还有一些小BUG需要修改，比如：在简介里输入全角字符（比如·和——），会导致后面的字符都无法保存。P.S. 单引号、双引号和&#8221;&amp;&#8221;容易引起JS错误，我把它们都屏蔽了-_____-b</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2007/03/13/mapfolio/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>YY流界面之动态图标导航栏</title>
		<link>http://www.limboy.com/2007/03/03/iconbar/</link>
		<comments>http://www.limboy.com/2007/03/03/iconbar/#comments</comments>
		<pubDate>Sat, 03 Mar 2007 06:10:03 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[界面]]></category>

		<guid isPermaLink="false">http://localhost/wordpress/index.php/2007/03/03/iconbar/</guid>
		<description><![CDATA[做这个导航栏的初衷，是想在公司产品的后台界面里，模仿MAC OS X系统的dock效果，所谓dock，就是OS X桌面底部那条显眼的工具栏，我的UBUNTU桌面里也有类似的效果……
实际上我也没用过MAC，所以是凭想象做的，演示页面在此
右上角的导航栏是默认的效果，鼠标滑过时图标变大，会推挤旁边的图标。
下面第一排去掉了推挤效果。
第二排加入了左右移动的功能，图标的数量远远超出页面的宽度，只显示其中一部分，在导航栏上左右移动鼠标时，整个导航栏会向相反方向滑动，显示出隐藏的图标。
第三排把移动的操作改到了左右两侧的箭头，鼠标停留在箭头上时，导航栏就会向对应的方向滑动，鼠标离开箭头时滑动停止，当滑动到最末端的图标时，自动停止。
先实现导航栏的默认效果，HTML如下：
&#60;div class=&#34;iconbarout&#34;&#62;
&#160;
&#60;div&#160;id=&#34;iconbar0&#34; class=&#34;iconbar&#34; &#62;
&#160;
&#160;&#60;ul style=&#34;margin-left:0px;&#34;&#62;
&#160; 
&#160;&#60;li&#62;
&#160; &#60;a&#160;href=&#34;#&#34;&#62;
&#160;
&#160;&#160; &#60;img&#160;src=&#34;images/icon7.png&#34; style=&#34;width:68px;height:68px;&#34; onload=&#34;alphaPNG(this);&#34; onmouseover=&#34;largeIcon(this);&#34; onmouseout=&#34;reIcon(this);&#34; /&#62;
&#160;
&#160;&#160; &#60;span&#62;link7&#60;/span&#62;
&#160; &#60;/a&#62;
&#160;&#60;/li&#62;
&#160;
&#160;
&#160;&#60;li&#62;
&#160; &#60;a&#160;href=&#34;#&#34;&#62;
&#160;
&#160;&#160; &#60;img&#160;src=&#34;images/icon6.png&#34; style=&#34;width:68px;height:68px;&#34; onload=&#34;alphaPNG(this);&#34; onmouseover=&#34;largeIcon(this);&#34; onmouseout=&#34;reIcon(this);&#34; /&#62;
&#160;
&#160;&#160; &#60;span&#62;link6&#60;/span&#62;
&#160; &#60;/a&#62;
&#160;&#60;/li&#62;
&#160;
&#160;
&#160;&#60;/ul&#62;
&#60;/div&#62;
&#160;
&#160;
&#60;/div&#62;
为了追求立体感，图标不能有背景色，所以必须用透明PNG图片，这里用&#60;img&#62;标签插入图片，是因为要实现图标的缩小放大效果（CSS背景里的图片只能控制位置，不能改变大小），图标的长宽要写在元素的style属性里，方便JS程序控制。
由于IE6不支持PNG的透明背景，必须用滤镜来做HACK才能达到一样的效果，而滤镜只能写在CSS的背景属性里…………为了解决这个矛盾，就要依靠JS了：
function alphaPNG(png)
{
var&#160;aVersion=navigator.appVersion.split(&#34;MSIE&#34;);
&#160;
var&#160;version=parseInt(aVersion[1]);
var&#160;pp=png.parentNode;
&#160;
if(&#160;(version&#62;=5.5) &#38;&#38; (version&#60;7) &#38;&#38; (document.body.filters) )
&#160;
{
&#160;var mout=png.onmouseout.toString();
&#160;
&#160;var mover=png.onmouseover.toString();
&#160;
&#160;alphaHTML=&#34;&#60;span style=\&#34;cursor:pointer;filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='&#34;+png.src+&#34;');display:block;width:&#34;+png.style.width+&#34;;height:&#34;+png.style.height+&#34;;\&#34; onmouseover=\&#34;&#34;+mover.substring(mover.indexOf(&#34;{&#34;)+1,mover.lastIndexOf(&#34;}&#34;))+&#34;\&#34; onmouseout=\&#34;&#34;+mout.substring(mout.indexOf(&#34;{&#34;)+1,mout.lastIndexOf(&#34;}&#34;))+&#34;\&#34; &#62;&#60;/span&#62;&#34;;
&#160;
&#160;png.outerHTML=alphaHTML;
}
&#160;
}
这个函数已经写在图片的onload事件里了，会在IMG标签的内容加载完后触发（这个事件虽好，也不能到处乱用，根据伟大的犀牛书V5，onload只支持body, frameset, img），函数先判断浏览器类型和版本（IE7支持透明PNG），先创建一个span元素，IMG标签的所有属性、事件都原样COPY到SPAN上，而PNG图片则放到SPAN的背景里，用滤镜处理成透明，注意滤镜属性里必须要有sizingMethod=scale。最后用outerHTML（只有IE支持）把该IMG替换成span。
导航栏的样式：
.iconbarout
{
width:770px;
&#160;
position:absolute;
top:40px;right:10px;
&#160;
}
&#160;
.iconbar{
overflow:hidden;
float:left;
&#160;
}
&#160;
.iconbar&#160;li{
float:right;
padding:0px;
&#160;
width:auto;
text-align:center;
margin:0&#160;16px 0 0px;
&#160;
}
.iconbar&#160;li span{
color:#333;
font-weight:600;
&#160;
width:auto;
display:block;
float:none;
&#160;
margin:0px&#160;auto;
}
.iconbar&#160;li a img{
margin:0px&#160;auto;
&#160;
float:none;
}
.iconbar&#160;li a{
text-align:center;
&#160;
float:none;
margin:0px&#160;auto;
}
.iconbar&#160;li img{
&#160;
border:0px;
float:left;
}
这样就在IE和Firefox里实现一样的视觉效果了（这里存在一个问题，为了保证图标放大后的清晰度，初始的图标都是缩小的，在IE7和Firefox里都会看到一点锯齿，而IE6由于用了滤镜，缩小的图标边缘仍然是平滑的-_____-b）
接下来做鼠标滑过的放大缩小效果。JS的动画效果一般是利用setTimeout或setInterval的延迟功能，反复循环来实现的。为了避免这些图标在运行函数时发生冲突，我把缩放的动画效果封装到了一个类里：
/* zoom class by Dexter.Yy
********************************************************/
&#160;
function&#160;animeZoom(ico,gWidth,gHeight,nWidth,nHeight)
&#160;
{
this.png=ico;
this.iheight=nHeight;
&#160;
this.iWidth=nWidth;
this.goWidth=gWidth;
this.goHeight=gHeight;
&#160;
this.rico;
}
&#160;
animeZoom.prototype.zoomEvent=function()
&#160;
{
if(this.iWidth&#60;this.goWidth)
{
&#160;this.goEnlarge();
&#160;
}
else&#160;if(this.iWidth&#62;this.goWidth)
{
&#160;
&#160;this.goReduce();
}
&#160;
}
&#160;
animeZoom.prototype.goEnlarge=function()
&#160;
{
this.png.style.width=this.goWidth+&#34;px&#34;;
&#160;
this.png.style.height=this.goWidth+&#34;px&#34;;
&#160;
}
&#160;
animeZoom.prototype.goReduce=function()
{
var&#160;obj=this;
&#160;
var&#160;h=parseInt(this.png.style.height);
&#160;
var&#160;w=parseInt(this.png.style.width);
&#160;
if(w&#62;this.goWidth)
{
&#160;this.png.style.width=w-2+&#34;px&#34;;
&#160;
&#160;this.png.style.height=h-2+&#34;px&#34;;
&#160;
&#160;this.rico=setTimeout(function(){obj.goReduce();},30);
&#160;
}
else
{
&#160;window.clearTimeout(this.rico);
&#160;
}
}
使用时要传5个参数：目标对象、期望达到的宽度、期望达到的高度、原始宽度、原始高度，像这样：
function [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bp3.blogger.com/_FPgtQV0mSoM/ReiWVwgyOlI/AAAAAAAAACo/MbsEPQcQ5Ro/s1600-h/2.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_FPgtQV0mSoM/ReiWVwgyOlI/AAAAAAAAACo/MbsEPQcQ5Ro/s320/2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5037441483757730386" /></a>做这个导航栏的初衷，是想在公司产品的后台界面里，模仿MAC OS X系统的dock效果，所谓dock，就是OS X桌面底部那条显眼的工具栏，我的<a href="http://www.yupoo.com/photos/view?id=ff80808110e9bc110110f4bcebc43fe2" title="来YUPOO看我的照片">UBUNTU桌面</a>里也有类似的效果……</p>
<p>实际上我也没用过MAC，所以是凭想象做的，<a href="http://demo.limboy.com/iconmenu.htm">演示页面在此</a></p>
<p>右上角的导航栏是默认的效果，鼠标滑过时图标变大，会推挤旁边的图标。<span id="more-83"></span><br />
下面第一排去掉了推挤效果。<br />
第二排加入了左右移动的功能，图标的数量远远超出页面的宽度，只显示其中一部分，在导航栏上左右移动鼠标时，整个导航栏会向相反方向滑动，显示出隐藏的图标。<br />
第三排把移动的操作改到了左右两侧的箭头，鼠标停留在箭头上时，导航栏就会向对应的方向滑动，鼠标离开箭头时滑动停止，当滑动到最末端的图标时，自动停止。</p>
<p>先实现导航栏的默认效果，HTML如下：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Olive;">&lt;</span><span style="color: Green;">div</span><span style="color: Gray;"> </span><span style="color: #00008b;">class</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">iconbarout</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">&lt;</span><span style="color: Green;">div</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">id</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">iconbar0</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">class</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">iconbar</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">ul</span><span style="color: Gray;"> </span><span style="color: #00008b;">style</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">margin-left:0px;</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp; </span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">li</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">a</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">href</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">#</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">img</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">src</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">images/icon7.png</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">style</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">width:68px;height:68px;</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">onload</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">alphaPNG(this);</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">onmouseover</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">largeIcon(this);</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">onmouseout</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">reIcon(this);</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">span</span><span style="color: Olive;">&gt;</span><span style="color: Gray;">link7</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">span</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: Olive;">&lt;/</span><span style="color: Green;">a</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">li</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">li</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">a</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">href</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">#</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">img</span><span style="color: Gray;">&nbsp;</span><span style="color: #00008b;">src</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">images/icon6.png</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">style</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">width:68px;height:68px;</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">onload</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">alphaPNG(this);</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">onmouseover</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">largeIcon(this);</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: #00008b;">onmouseout</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">reIcon(this);</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">span</span><span style="color: Olive;">&gt;</span><span style="color: Gray;">link6</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">span</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp; </span><span style="color: Olive;">&lt;/</span><span style="color: Green;">a</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">li</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">ul</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Olive;">&lt;/</span><span style="color: Green;">div</span><span style="color: Olive;">&gt;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">&lt;/</span><span style="color: Green;">div</span><span style="color: Olive;">&gt;</span></li></ol></div>
<p>为了追求立体感，图标不能有背景色，所以必须用透明PNG图片，这里用&lt;img&gt;标签插入图片，是因为要实现图标的缩小放大效果（CSS背景里的图片只能控制位置，不能改变大小），图标的长宽要写在元素的style属性里，方便JS程序控制。</p>
<p>由于IE6不支持PNG的透明背景，必须用滤镜来做HACK才能达到一样的效果，而滤镜只能写在CSS的背景属性里…………为了解决这个矛盾，就要依靠JS了：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Blue;">alphaPNG</span><span style="color: Olive;">(</span><span style="color: Blue;">png</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">aVersion</span><span style="color: Gray;">=</span><span style="color: Teal;">navigator</span><span style="color: Gray;">.</span><span style="color: Blue;">appVersion</span><span style="color: Gray;">.</span><span style="color: Blue;">split</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">MSIE</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">version</span><span style="color: Gray;">=</span><span style="color: Blue;">parseInt</span><span style="color: Olive;">(</span><span style="color: Blue;">aVersion</span><span style="color: Olive;">[</span><span style="color: Maroon;">1</span><span style="color: Olive;">])</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">pp</span><span style="color: Gray;">=</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">parentNode</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Gray;">&nbsp;</span><span style="color: Olive;">(</span><span style="color: Blue;">version</span><span style="color: Gray;">&gt;=</span><span style="color: Maroon;">5.5</span><span style="color: Olive;">)</span><span style="color: Gray;"> &amp;&amp; </span><span style="color: Olive;">(</span><span style="color: Blue;">version</span><span style="color: Gray;">&lt;</span><span style="color: Maroon;">7</span><span style="color: Olive;">)</span><span style="color: Gray;"> &amp;&amp; </span><span style="color: Olive;">(</span><span style="color: Teal;">document</span><span style="color: Gray;">.</span><span style="color: Blue;">body</span><span style="color: Gray;">.</span><span style="color: Blue;">filters</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">mout</span><span style="color: Gray;">=</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">onmouseout</span><span style="color: Gray;">.</span><span style="color: Blue;">toString</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Green;">var</span><span style="color: Gray;"> </span><span style="color: Blue;">mover</span><span style="color: Gray;">=</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">onmouseover</span><span style="color: Gray;">.</span><span style="color: Blue;">toString</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">alphaHTML</span><span style="color: Gray;">=</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">&lt;span style=</span><span style="color: Navy;">\&quot;</span><span style="color: Red;">cursor:pointer;filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">+</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">src</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">');display:block;width:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">+</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">width</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">;height:</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">+</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">height</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">;</span><span style="color: Navy;">\&quot;</span><span style="color: Red;"> onmouseover=</span><span style="color: Navy;">\&quot;</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">+</span><span style="color: Blue;">mover</span><span style="color: Gray;">.</span><span style="color: Blue;">substring</span><span style="color: Olive;">(</span><span style="color: Blue;">mover</span><span style="color: Gray;">.</span><span style="color: Blue;">indexOf</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">{</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">+</span><span style="color: Maroon;">1</span><span style="color: Gray;">,</span><span style="color: Blue;">mover</span><span style="color: Gray;">.</span><span style="color: Blue;">lastIndexOf</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">}</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">))</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Navy;">\&quot;</span><span style="color: Red;"> onmouseout=</span><span style="color: Navy;">\&quot;</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">+</span><span style="color: Blue;">mout</span><span style="color: Gray;">.</span><span style="color: Blue;">substring</span><span style="color: Olive;">(</span><span style="color: Blue;">mout</span><span style="color: Gray;">.</span><span style="color: Blue;">indexOf</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">{</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">)</span><span style="color: Gray;">+</span><span style="color: Maroon;">1</span><span style="color: Gray;">,</span><span style="color: Blue;">mout</span><span style="color: Gray;">.</span><span style="color: Blue;">lastIndexOf</span><span style="color: Olive;">(</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">}</span><span style="color: #8b0000;">&quot;</span><span style="color: Olive;">))</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Navy;">\&quot;</span><span style="color: Red;"> &gt;&lt;/span&gt;</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">outerHTML</span><span style="color: Gray;">=</span><span style="color: Blue;">alphaHTML</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>这个函数已经写在图片的onload事件里了，会在IMG标签的内容加载完后触发（这个事件虽好，也不能到处乱用，根据伟大的犀牛书V5，onload只支持body, frameset, img），函数先判断浏览器类型和版本（IE7支持透明PNG），先创建一个span元素，IMG标签的所有属性、事件都原样COPY到SPAN上，而PNG图片则放到SPAN的背景里，用滤镜处理成透明，注意滤镜属性里必须要有sizingMethod=scale。最后用outerHTML（只有IE支持）把该IMG替换成span。</p>
<p>导航栏的样式：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Blue;">.iconbarout</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">width:</span><span style="color: Maroon;">770</span><span style="color: Red;">px</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">position:</span><span style="color: Red;">absolute</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">top:</span><span style="color: Maroon;">40</span><span style="color: Red;">px</span><span style="color: Gray;">;</span><span style="color: Green;">right:</span><span style="color: Maroon;">10</span><span style="color: Red;">px</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">.iconbar</span><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">overflow:</span><span style="color: Red;">hidden</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">float:</span><span style="color: Red;">left</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">.iconbar</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">li</span><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">float:</span><span style="color: Red;">right</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">padding:</span><span style="color: Maroon;">0</span><span style="color: Red;">px</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">width:</span><span style="color: Red;">auto</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">text-align:</span><span style="color: Red;">center</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">margin:</span><span style="color: Maroon;">0</span><span style="color: Gray;">&nbsp;</span><span style="color: Maroon;">16</span><span style="color: Red;">px</span><span style="color: Gray;"> </span><span style="color: Maroon;">0</span><span style="color: Gray;"> </span><span style="color: Maroon;">0</span><span style="color: Red;">px</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Blue;">.iconbar</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">li</span><span style="color: Gray;"> </span><span style="color: Blue;">span</span><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">color:</span><span style="color: #00008b;">#333</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">font-weight:</span><span style="color: Maroon;">600</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">width:</span><span style="color: Red;">auto</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">display:</span><span style="color: Red;">block</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">float:</span><span style="color: Red;">none</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">margin:</span><span style="color: Maroon;">0</span><span style="color: Red;">px</span><span style="color: Gray;">&nbsp;</span><span style="color: Red;">auto</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Blue;">.iconbar</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">li</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Gray;"> </span><span style="color: Blue;">img</span><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">margin:</span><span style="color: Maroon;">0</span><span style="color: Red;">px</span><span style="color: Gray;">&nbsp;</span><span style="color: Red;">auto</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">float:</span><span style="color: Red;">none</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Blue;">.iconbar</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">li</span><span style="color: Gray;"> </span><span style="color: Blue;">a</span><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">text-align:</span><span style="color: Red;">center</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">float:</span><span style="color: Red;">none</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">margin:</span><span style="color: Maroon;">0</span><span style="color: Red;">px</span><span style="color: Gray;">&nbsp;</span><span style="color: Red;">auto</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Blue;">.iconbar</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">li</span><span style="color: Gray;"> </span><span style="color: Blue;">img</span><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">border:</span><span style="color: Maroon;">0</span><span style="color: Red;">px</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">float:</span><span style="color: Red;">left</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>这样就在IE和Firefox里实现一样的视觉效果了（这里存在一个问题，为了保证图标放大后的清晰度，初始的图标都是缩小的，在IE7和Firefox里都会看到一点锯齿，而IE6由于用了滤镜，缩小的图标边缘仍然是平滑的-_____-b）</p>
<p>接下来做鼠标滑过的放大缩小效果。JS的动画效果一般是利用setTimeout或setInterval的延迟功能，反复循环来实现的。为了避免这些图标在运行函数时发生冲突，我把缩放的动画效果封装到了一个类里：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: #ffa500;">/* zoom class by Dexter.Yy</span></li>
<li><span style="color: #ffa500;">********************************************************/</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">function</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">animeZoom</span><span style="color: Olive;">(</span><span style="color: Blue;">ico</span><span style="color: Gray;">,</span><span style="color: Blue;">gWidth</span><span style="color: Gray;">,</span><span style="color: Blue;">gHeight</span><span style="color: Gray;">,</span><span style="color: Blue;">nWidth</span><span style="color: Gray;">,</span><span style="color: Blue;">nHeight</span><span style="color: Olive;">)</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">png</span><span style="color: Gray;">=</span><span style="color: Blue;">ico</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">iheight</span><span style="color: Gray;">=</span><span style="color: Blue;">nHeight</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">iWidth</span><span style="color: Gray;">=</span><span style="color: Blue;">nWidth</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goWidth</span><span style="color: Gray;">=</span><span style="color: Blue;">gWidth</span><span style="color: Gray;">;</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goHeight</span><span style="color: Gray;">=</span><span style="color: Blue;">gHeight</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">rico</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">animeZoom</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">zoomEvent</span><span style="color: Gray;">=</span><span style="color: Green;">function</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">iWidth</span><span style="color: Gray;">&lt;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goWidth</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goEnlarge</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Green;">else</span><span style="color: Gray;">&nbsp;</span><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">iWidth</span><span style="color: Gray;">&gt;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goWidth</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goReduce</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">animeZoom</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">goEnlarge</span><span style="color: Gray;">=</span><span style="color: Green;">function</span><span style="color: Olive;">()</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">width</span><span style="color: Gray;">=</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goWidth</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">px</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">height</span><span style="color: Gray;">=</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goWidth</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">px</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">animeZoom</span><span style="color: Gray;">.</span><span style="color: Blue;">prototype</span><span style="color: Gray;">.</span><span style="color: Blue;">goReduce</span><span style="color: Gray;">=</span><span style="color: Green;">function</span><span style="color: Olive;">()</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">obj</span><span style="color: Gray;">=</span><span style="color: Green;">this</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">h</span><span style="color: Gray;">=</span><span style="color: Blue;">parseInt</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">height</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">w</span><span style="color: Gray;">=</span><span style="color: Blue;">parseInt</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">width</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">if</span><span style="color: Olive;">(</span><span style="color: Blue;">w</span><span style="color: Gray;">&gt;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">goWidth</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">width</span><span style="color: Gray;">=</span><span style="color: Blue;">w</span><span style="color: Gray;">-</span><span style="color: Maroon;">2</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">px</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">png</span><span style="color: Gray;">.</span><span style="color: Blue;">style</span><span style="color: Gray;">.</span><span style="color: Blue;">height</span><span style="color: Gray;">=</span><span style="color: Blue;">h</span><span style="color: Gray;">-</span><span style="color: Maroon;">2</span><span style="color: Gray;">+</span><span style="color: #8b0000;">&quot;</span><span style="color: Red;">px</span><span style="color: #8b0000;">&quot;</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">rico</span><span style="color: Gray;">=</span><span style="color: Blue;">setTimeout</span><span style="color: Olive;">(</span><span style="color: Green;">function</span><span style="color: Olive;">(){</span><span style="color: Blue;">obj</span><span style="color: Gray;">.</span><span style="color: Blue;">goReduce</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span><span style="color: Olive;">}</span><span style="color: Gray;">,</span><span style="color: Maroon;">30</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Green;">else</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Gray;">&nbsp;</span><span style="color: Teal;">window</span><span style="color: Gray;">.</span><span style="color: Blue;">clearTimeout</span><span style="color: Olive;">(</span><span style="color: Green;">this</span><span style="color: Gray;">.</span><span style="color: Blue;">rico</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Olive;">}</span></li></ol></div>
<p>使用时要传5个参数：目标对象、期望达到的宽度、期望达到的高度、原始宽度、原始高度，像这样：</p>
<div class="hl-surround"><ol class="hl-main ln-show" title="Double click to hide line number." ondblclick = "linenumber(this)"><li class="hl-firstline"><span style="color: Green;">function</span><span style="color: Gray;"> </span><span style="color: Blue;">largeIcon</span><span style="color: Olive;">(</span><span style="color: Blue;">png</span><span style="color: Olive;">)</span></li>
<li><span style="color: Olive;">{</span></li>
<li><span style="color: Green;">var</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">lIco</span><span style="color: Gray;">=</span><span style="color: Green;">new</span><span style="color: Gray;"> </span><span style="color: Blue;">animeZoom</span><span style="color: Olive;">(</span><span style="color: Blue;">png</span><span style="color: Gray;">,</span><span style="color: Maroon;">91</span><span style="color: Gray;">,</span><span style="color: Maroon;">91</span><span style="color: Gray;">,</span><span style="color: Maroon;">68</span><span style="color: Gray;">,</span><span style="color: Maroon;">68</span><span style="color: Olive;">)</span><span style="color: Gray;">;</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Blue;">lIco</span><span style="color: Gray;">.</span><span style="color: Blue;">zoomEvent</span><span style="color: Olive;">()</span><span style="color: Gray;">;</span></li>
<li><span style="color: Olive;">}</span></li>
<li><span style="color: Gray;">&nbsp;</span></li>
<li><span style="color: Green;">function</span><span style="color: Gray;">&nbsp;</span><span style="color: Blue;">reIcon</span><span style="color
