<?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 混沌海狂想</title>
	<atom:link href="http://www.limboy.com/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>“iPhone人工智能”的背后</title>
		<link>http://www.limboy.com/2011/10/08/ai-in-iphone/</link>
		<comments>http://www.limboy.com/2011/10/08/ai-in-iphone/#comments</comments>
		<pubDate>Fri, 07 Oct 2011 19:02:06 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[SF/F]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=482</guid>
		<description><![CDATA[本来想直接推荐这篇9to5Mac的访谈：《Siri联合创始人: 苹果的“语音助手”将改变世界》 ，但是要补充的太多，豆瓣说的字数不够用了……
我在iPhone 4S发布会之前就看过这篇文章，居然没注意到关键信息……我一直以为Nuance才是“iPhone语音识别”背后的核心技术，因为Nuance市值超过60亿，因为Apple买了Nuance的语音技术授权，因为Nuance跟IBM合作研发了人工智能Watson（其实除了语音识别和理解问题的部分，这家伙剩余的技术就是搜索和数据挖掘罢⋯⋯）

今天看了iPhone 4S发布会视频的后半段，感觉Siri（特别是结合Wolfram Alpha之后）绝对被低估了，现场演示和广告都相当惊艳，让人浮想联翩，无愧于amazing、incredible之类的乔式营销词汇——这才不是什么“语音识别”！这是霹雳游侠里的KITT！高智能方程式里的Asurada！东之伊甸里的Juiz！星际争霸里的人族Adjutant！Portal里的GLaDOS！2001太空漫游里的HAL9000！⋯⋯ 


恰好今天又传出Nuance收购手机输入法Swype的新闻，其中都提到T9输入法是Nuance的业务之一，我才知道Nuance的业务其实很广……
重读那篇访谈，才注意到根源是DARPA发起的CALO项目，DARPA（美国国防高级研究计划局）在我心目中是跟硅谷并列的美国科技两大引擎之一，它比硅谷的VC更大胆更有前瞻性，赞助过一大堆充满科幻风格的未来技术，其中就包括投资数亿的“学习型个人助理”（PAL）计划，目的是为指挥官和作战人员提供革命性的辅助系统，快速掌握战场状况并辅助决策——有没有想起一大票FPS游戏里的辅助语音系统，比如HALO中跟&#8221;超级战士&#8221;计划配套的，UNSC研发的最强人工智能Cortana⋯⋯

PAL主要涉及的技术是人工智能（具体一点是机器学习和自然语言），而CALO正是PAL的子项目，占用了首期投资的76%，全称是&#8221;Cognitive Assistant that Learns and Organizes&#8221;，但也表示拉丁文&#8221;calonis&#8221;，意思是“soldier’s servant”（英灵！？⋯⋯）

参与CALO项目的强力组织包括麻省理工、斯坦福、卡内基梅隆大学、UC伯克利、波音等20多家，但牵头的是斯坦福的SRI International，而Apple收购的Siri正是SRI的嫡系，Nuance同样也是SRI孵化出来的——比起访谈里的信息，更值得注意的是：PAL计划是2003年启动的，Siri在2007年创立，直接来源于SRI在CALO项目中的工作，而Nuance早在1994年就创建了，前身是SRI的STAR实验室（Speech Technology and Research）⋯⋯
所以Norman Winarsky说Nuance只是Siri中可替换的“语音识别组件”——Nuance的业务只是语音技术，而Siri开发的是人工智能！

那么最实用的好消息便是：Nuance在上海和北京望京都有研发中心，一直在做国内各种方言的识别，“在广东话和普通话，我们是下了很大的功夫，然后我们把普通话的口音都覆盖，所以像我是香港口音、或者台湾国语、四川国语、东北国语其实全部是可以覆盖的”，而Apple可以直接利用“语音组件”的这些进展～
P.S. Thank you, Steve. Bravo.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.limboy.com/wp-content/uploads/2011/10/29741-358549_main_super.jpg" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/10/29741-358549_main_super.jpg" style="width:150px;float:left;margin:0 15px 10px 0;"  /></a>本来想直接推荐这篇9to5Mac的访谈：<a target="_blank" href="http://www.leiphone.com/siri-assistant-world-changing.html">《Siri联合创始人: 苹果的“语音助手”将改变世界》</a> ，但是要补充的太多，<a target="_blank" href="http://shuo.douban.com/#!/Dexter_Yy">豆瓣说</a>的字数不够用了……</p>
<p>我在iPhone 4S发布会之前就看过这篇文章，居然没注意到关键信息……我一直以为Nuance才是“iPhone语音识别”背后的核心技术，因为Nuance市值超过60亿，因为Apple买了Nuance的语音技术授权，因为Nuance跟IBM合作研发了<a target="_blank" href="http://nota.lukhnos.org/post/3380874795">人工智能Watson</a>（其实除了语音识别和<a target="_blank" href="http://www.52nlp.cn/%E7%AB%8B%E5%A7%94%E7%A7%91%E6%99%AE-%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%89%8D%E7%94%9F%E4%BB%8A%E4%B8%96">理解问题</a>的部分，这家伙剩余的技术就是搜索和数据挖掘罢⋯⋯）<span id="more-482"></span></p>
<div style="clear:both;"></div>
<p>今天看了iPhone 4S发布会视频的后半段，感觉Siri（特别是结合<a target="_blank" href="http://www.tedtochina.com/2010/06/04/stephen-wolfram-on-the-computational-future/">Wolfram Alpha</a>之后）绝对被低估了，现场演示和广告都相当惊艳，让人浮想联翩，无愧于amazing、incredible之类的乔式营销词汇——这才不是什么“语音识别”！这是霹雳游侠里的<a  target="_blank" href="http://en.wikipedia.org/wiki/File:Knight_Rider_Supercar_KITT_instrumentation.jpg">KITT</a>！高智能方程式里的<a target="_blank" href="http://zh.wikipedia.org/wiki/%E9%96%83%E9%9B%BB%E9%9C%B9%E9%9D%82%E8%BB%8A%E8%B3%BD%E8%BB%8A%E5%88%97%E8%A1%A8">Asurada</a>！<a  target="_blank" href="http://zh.wikipedia.org/zh/%E6%9D%B1%E4%B9%8B%E4%BC%8A%E7%94%B8">东之伊甸</a>里的Juiz！星际争霸里的人族Adjutant！Portal里的<a  target="_blank" href="http://www.guokr.com/article/59555/">GLaDOS</a>！2001太空漫游里的HAL9000！⋯⋯ </p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/10/siri-iphone-4s1.jpg" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/10/siri-iphone-4s1.jpg" style="width:400px;" /></a></p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/10/52-295x300.jpg" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/10/52-295x300.jpg"  width="295" height="300"   /></a></p>
<p>恰好今天又传出<a target="_blank" href="http://www.36kr.com/p/51312.html">Nuance收购手机输入法Swype</a>的新闻，其中都提到T9输入法是Nuance的业务之一，我才知道<a target="_blank" href="http://www.contactcenterbr.com/info.aspx?id=1973&amp;lm=7">Nuance的业务其实很广</a>……</p>
<p>重读那篇访谈，才注意到根源是DARPA发起的CALO项目，DARPA（美国国防高级研究计划局）在我心目中是跟硅谷并列的美国科技两大引擎之一，它比硅谷的VC更大胆更有前瞻性，赞助过一大堆充满科幻风格的<a target="_blank" href="http://science.solidot.org/article.pl?sid=11/08/19/1018234">未来技术</a>，其中就包括投资数亿的“学习型个人助理”（PAL）计划，目的是为指挥官和作战人员提供革命性的辅助系统，快速掌握战场状况并辅助决策——有没有想起一大票FPS游戏里的辅助语音系统，比如HALO中跟&#8221;超级战士&#8221;计划配套的，UNSC研发的最强人工智能Cortana⋯⋯</p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/10/Chiefcort.jpg" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/10/Chiefcort.jpg" style="width:300px;" /></a></p>
<p>PAL主要涉及的技术是人工智能（具体一点是机器学习和自然语言），而CALO正是PAL的子项目，占用了首期投资的76%，全称是&#8221;Cognitive Assistant that Learns and Organizes&#8221;，但也表示拉丁文&#8221;calonis&#8221;，意思是“soldier’s servant”（<a target="_blank" href="http://zh.wikipedia.org/wiki/Fate/stay_night#.E5.BE.9E.E8.80.85">英灵</a>！？⋯⋯）</p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/10/Screen-Shot-2011-10-08-at-2.14.42-AM.png" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/10/Screen-Shot-2011-10-08-at-2.14.42-AM.png" style="width:300px;" /></a></p>
<p>参与CALO项目的强力组织包括麻省理工、斯坦福、卡内基梅隆大学、UC伯克利、波音等20多家，但牵头的是斯坦福的SRI International，而Apple收购的Siri正是SRI的嫡系，Nuance同样也是SRI孵化出来的——比起访谈里的信息，更值得注意的是：PAL计划是2003年启动的，Siri在2007年创立，直接来源于SRI在CALO项目中的工作，而Nuance早在1994年就创建了，前身是SRI的STAR实验室（Speech Technology and Research）⋯⋯</p>
<p>所以Norman Winarsky说Nuance只是Siri中可替换的“语音识别组件”——Nuance的业务只是语音技术，而Siri开发的是人工智能！</p>
<p><a href="http://www.douban.com/photos/album/49655403/"><img src="http://www.limboy.com/wp-content/uploads/2011/10/p1029523786.jpg"  title="We do what we must because we can!" style="width:380px;" /></a></p>
<p>那么最实用的好消息便是：Nuance在上海和北京望京都有研发中心，一直在做国内各种方言的识别，“在广东话和普通话，我们是下了很大的功夫，然后我们把普通话的口音都覆盖，所以像我是香港口音、或者台湾国语、四川国语、东北国语其实全部是可以覆盖的”，而Apple可以直接利用“语音组件”的这些进展～</p>
<p>P.S. <a  target="_blank" href="http://www.douban.com/note/176291524/">Thank you, Steve. Bravo.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2011/10/08/ai-in-iphone/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<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>被遗忘的vim插件管理程序⋯⋯</title>
		<link>http://www.limboy.com/2011/09/25/vim-plugin-scaner/</link>
		<comments>http://www.limboy.com/2011/09/25/vim-plugin-scaner/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 14:56:17 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[工具]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=454</guid>
		<description><![CDATA[众所周知vim缺少官方的包管理机制，刚开始接触vim的人往往都有IDE情结，喜欢四处搜罗插件，光是ftplugin目录就要塞进十几个脚本，把“编辑器之神”武装得包罗万象无所不能，然而这些卑微的凡人，尽管手握神器，总归还是要身陷在繁忙的日常coding中，最初的欣喜和热情也在日复一日中消散，由于没有定期更新这些脚本文件的办法，更没有精力去逐个关注，渐渐就忘记了兼容性升级，忘记了:com，忘记了键位映射，忘记了操作符，最后可能连插件名字和功能都记不得了⋯⋯
好罢这不是那种“我有一个朋友”式的故事，我只是想说一个自动化的插件管理程序能解决这种维护烦恼，起码不至于等到世界变了OS都升级了出现严重兼容性问题了编辑器都启动不了之后再去排查原因移除长久不用的插件⋯⋯
这本书告诉我们技术不是孤立发展的，当你察觉到一种需求的时候，意味着大半个开发者社区都有了这种需求，当你被逼得动手尝试idea，意味着同类项目已经更新了一个大版本，所以说当前比较完善的vim包管理工具大概有以下这么几种⋯⋯
https://github.com/tpope/vim-pathogen
https://github.com/gmarik/vundle
https://github.com/c9s/Vimana
但是我很不喜欢那种自己建私有目录占地为王的项目，最后那个林佑安老爷的程序是perl的，因为够轻量我很早就帮他宣传过，不过当时使用很麻烦，后来就没关注了，没想到已经开发的这么完善，还有日本perl基友同好的参与⋯⋯
所以去年我写了一个程序来自动化插件的查找和升级——没错，本文是从去年穿越过来的，以上都是去年的想法⋯⋯
https://github.com/dexteryy/yy-vimscript/blob/master/pluginscaner.py
因为vim脚本并不算很成熟的软件分发机制，.vim目录也不是很靠谱的组织结构，我不想把它们搞成一个黑箱，这个python脚本只是替代了一部分人工行为：先看看我装了哪些插件 -> 访问vim.org，搜索插件名称 -> 在插件主页下方的下载列表里找到最新版本 -> 对比版本号或日期⋯⋯
初次执行是这个样子：

结果是这个样子：

不要被那些0吓到，这显然是因为没初始化索引⋯⋯我懒得做初始化选项⋯⋯
在命令后面加上用单个插件名称，就会提示下载方式：

不管你答yes还是no，这个插件都算作升级过了⋯⋯
逐个这么执行一遍⋯⋯今后就能正常的用它检查版本更新了⋯⋯
好罢我发这篇文章是希望有人能继续完善这个脚本命令，或许有人像我一样有控制欲，只愿意接受这种自动检查和辅助安装的包管理方式。我懒得写后续的功能了，所以把它搁了一年⋯⋯
如果你要修改代码，记得把里面的google api key换掉⋯⋯
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.limboy.com/wp-content/uploads/2009/06/picture-4.png"><img src="http://www.limboy.com/wp-content/uploads/2009/06/picture-4.png" style="width:175px;float:left;margin:0 10px 10px 0;" /></a>众所周知vim缺少官方的包管理机制，刚开始接触vim的人往往都有IDE情结，喜欢四处搜罗插件，光是ftplugin目录就要塞进十几个脚本，把“编辑器之神”武装得包罗万象无所不能，然而这些卑微的凡人，尽管手握神器，总归还是要身陷在繁忙的日常coding中，最初的欣喜和热情也在日复一日中消散，由于没有定期更新这些脚本文件的办法，更没有精力去逐个关注，渐渐就忘记了兼容性升级，忘记了:com，忘记了键位映射，忘记了操作符，最后可能连插件名字和功能都记不得了⋯⋯</p>
<p>好罢这不是那种“我有一个朋友”式的故事，我只是想说一个自动化的插件管理程序能解决这种维护烦恼，起码不至于等到世界变了OS都升级了出现严重兼容性问题了编辑器都启动不了之后再去排查原因移除长久不用的插件⋯⋯<span id="more-454"></span></p>
<p><a href="http://book.douban.com/subject/4778063/" target="_blank">这本书</a>告诉我们技术不是孤立发展的，当你察觉到一种需求的时候，意味着大半个开发者社区都有了这种需求，当你被逼得动手尝试idea，意味着同类项目已经更新了一个大版本，所以说当前比较完善的vim包管理工具大概有以下这么几种⋯⋯</p>
<p><a href="https://github.com/tpope/vim-pathogen" target="_blank">https://github.com/tpope/vim-pathogen</a><br />
<a href="https://github.com/gmarik/vundle" target="_blank">https://github.com/gmarik/vundle</a><br />
<a href="https://github.com/c9s/Vimana" target="_blank">https://github.com/c9s/Vimana</a></p>
<p>但是我很不喜欢那种自己建私有目录占地为王的项目，最后那个林佑安老爷的程序是perl的，因为够轻量我很早就帮他宣传过，不过当时使用很麻烦，后来就没关注了，没想到已经开发的这么完善，还有日本perl<del>基友</del>同好的参与⋯⋯</p>
<p>所以去年我写了一个程序来自动化插件的查找和升级——没错，本文是从去年穿越过来的，以上都是去年的想法⋯⋯</p>
<p><a href="https://github.com/dexteryy/yy-vimscript/blob/master/pluginscaner.py" target="_blank">https://github.com/dexteryy/yy-vimscript/blob/master/pluginscaner.py</a></p>
<p>因为vim脚本并不算很成熟的软件分发机制，.vim目录也不是很靠谱的组织结构，我不想把它们搞成一个黑箱，<a href="https://github.com/dexteryy/yy-vimscript/blob/master/pluginscaner.py" target="_blank">这个python脚本</a>只是替代了一部分人工行为：先看看我装了哪些插件 -> 访问vim.org，搜索插件名称 -> 在插件主页下方的下载列表里找到最新版本 -> 对比版本号或日期⋯⋯</p>
<p>初次执行是这个样子：</p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/09/p173144456-1.jpg"><img src="http://www.limboy.com/wp-content/uploads/2011/09/p173144456-1.jpg" alt="" title="p173144456-1" width="317" height="676" class="alignnone size-full wp-image-455" /></a></p>
<p>结果是这个样子：</p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/09/p173144456-2.jpg"><img src="http://www.limboy.com/wp-content/uploads/2011/09/p173144456-2.jpg" alt="" title="p173144456-2" width="350" height="563" class="alignnone size-full wp-image-456" /></a></p>
<p>不要被那些0吓到，这显然是因为没初始化索引⋯⋯我懒得做初始化选项⋯⋯</p>
<p>在命令后面加上用单个插件名称，就会提示下载方式：</p>
<p><a href="http://www.limboy.com/wp-content/uploads/2011/09/p173144456-3.jpg" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/09/p173144456-3.jpg" alt="" title="p173144456-3" style="width:400px" class="alignnone size-full wp-image-457" /></a></p>
<p>不管你答yes还是no，这个插件都算作升级过了⋯⋯</p>
<p>逐个这么执行一遍⋯⋯今后就能正常的用它检查版本更新了⋯⋯</p>
<p>好罢我发这篇文章是希望有人能继续完善这个脚本命令，或许有人像我一样有控制欲，只愿意接受这种自动检查和辅助安装的包管理方式。我懒得写后续的功能了，所以把它搁了一年⋯⋯</p>
<p>如果你要修改代码，记得把里面的google api key换掉⋯⋯</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2011/09/25/vim-plugin-scaner/feed/</wfw:commentRss>
		<slash:comments>5</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>一个美术宅的传奇</title>
		<link>http://www.limboy.com/2011/05/02/tiles-legend/</link>
		<comments>http://www.limboy.com/2011/05/02/tiles-legend/#comments</comments>
		<pubDate>Mon, 02 May 2011 01:12:33 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[OpenSource]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=401</guid>
		<description><![CDATA[不论2D还是3D时代，游戏开发总是“美术密集型”的项目，假如把程序比作骨架和器官，把剧情设定和gameplay之类都比作灵魂，那么美工创造出来就是实实在在的血肉，是游戏中绝大部分的“内容”。对于非美工出身的独立游戏创作者，这些“内容”的来源总是一个大难题，当然总有些取巧的题材或设计能绕过这个槛，但是也总能看到那些成功的例子都离不开丰满的视觉内容，甚至是独特的艺术风格，比如iOS平台上最火的那些“小制作”：有Grimm的Edward Gorey式维多利亚哥特，有Rolando搭上的芬兰插画家，还有最近Sword &#038; Sworcery EP那“淡淡忧伤”的像素画风……
实际上对那些想要制作游戏的宅男们来说，美工背景有天然优势，程序员离不开心灵手巧的美工，而美工却能不依赖可怜的程序员，这主要是因为程序员们有一种根深蒂固深入骨髓的恶习叫作“抽象”和“复用”，他们总是不甘心只把想要的东西简简单单实现出来，总是忍不住去把其中通用的、不变的、能反复利用的部分提取出来，完善成库、框架、引擎和工具，有极少数头脑发热耳鸣眼花鼻塞手贱腿抽筋的人甚至会继续折腾出一套“不需要编程”就能自由创作的强大工具……在这些资源和技术宅的帮助下，很多美术宅和性幻想达人们都顺畅的踏上了游戏制作之路……可参考《欢迎加入NHK!》里的山崎薫和佐藤，或现实世界里的武内崇和奈须蘑菇……
好罢以上都是“技术宅你们伤不起”系列的吐槽，其实不会写程序就像束缚了手脚去爬山，同样很辛苦。我想说的是，相对于代码和软件，可复用的美术资源实在是太稀缺了，如果你也曾经在网上搜寻过免费完整的游戏开发资源，一定体验过那种浪费大量时间仍一无所获的挫折感。
而今天要讲的，是一个站出来挑战这种现状的平凡宅男的故事。
国外有一些独立游戏为了回馈社区，会释出一些自己使用的代码和资源，如果留意过相关的声明，会发现很多开发者都注明“图像来自Reiner Prokein”，其中Ambardia网站上提供下载的那些帖图（tile）资源最壮观最让人惊喜：

而这些也都是同一个人创作的。
这个人没有wiki词条，在mobygames上没有介绍，一点名气都没有，但他有一个叫Reiner&#8217;s Tilesets的网站（旧版，新版），提供更海量的资源，全部是自己绘制，全部以freeware形式提供下载，没有任何好看的许可协议（比如CC-BY或GPL），没有任何限制，允许商业使用，允许随意修改，唯一的要求是你确实用它们做游戏（不准直接转卖），并且在商业作品的Credits名单里要包含他的名字。
那是一个更传奇式的名字，叫作Reiner &#8220;Tiles&#8221; Prokein，他是德国人，一直梦想制作自己的电脑游戏。最开始他不懂编程——他基本上什么都不懂，但他没有放弃，没有畏首畏尾，从99年秋天开始，他决定寻找一种不用编程就能制作游戏的软件。
他找到了前辈ambro的神帖：Ambrosine&#8217;s Game Creation Resources &#038; Classic Game Links
他逐个尝试，最后喜欢上rpgmaker 95，开始制作自己的第一个小型RPG。这个游戏完成了，但从来没有公开过，因为他后来得知破解版的rpgmaker有合法性方面的问题。
在这个过程中，他发现网络上缺乏用于制作游戏的免费图像资源，便开始自己绘制，最初他一个像素一个像素的手绘，接下来他发现了TrueSpace（Caligari公司推出的3D图形和动画渲染工具，现在已经被微软收购，用于虚拟地球项目，可免费下载），开始学习所有跟图像渲染有关的知识。
因为不会编程，Reiner制作游戏的努力始终伴随着挫折感，而学习编程看上去又遥不可及。但他没有放弃，他继续搜寻，又发现了rpgmaker.net，在这个社区里能找到大量处于beta甚至alpha阶段的游戏制作软件，他开始参与到rpgstudio的开发中，为它创作帖图资源，并且从那个时候起开始建设自己的主页，也就是“Reiner&#8217;s Tilesets”，那是2000年春天。
但是要完成一个像rpgstudio这样的项目，所需时间远超他的想象，而这个项目最后也被废止了。
他仍然想要做游戏，这次他找到了MMF（Multimedia Fusion）的主页，来自法国Clickteam公司的这款软件前身就是著名的《游戏工厂》（TGF），只需要点击和托拽就能完成程序逻辑，还有大量扩展，Reiner觉得他终于找到了自己想要的，全心全意的投入其中。已经是2000年冬天。
2007年，Reiner在主页上更新了自己的近况，七年过去了，他没有拿出什么引入注目的游戏，不过他声称在尝试开发3D游戏，他现在主要用3D Gamestudio ，MMF有时也用，这意味着他不再像以前那样惧怕编程了，至少学习了一点lite-C（脚本语言）
2010年，Reiner再次更新，原来过去三年他都在克服某些身体健康方面的问题，从Caligari公司接的一些软件测试工作也耗费了他很多时间，总之他没有完成那个3D游戏，但是跟以往的文字一样，他喜欢在段落的末尾用笑脸代替句号：“But i never give up, and i don&#8217;t stop dreaming :)”
2011年春天，Reiner用wordpress重建了自己的tileset网站，没有德国游戏门户4players.de和广告的支持，他必须自己支付服务器费用了，末尾仍然没忘记笑脸：“But i am more than willing to pay this price :)”
这个故事还没结束，在99~00年的高潮之后，也许一直都会这么平淡无奇，但不知为什么让我觉得很温暖，忍不住分享一下。
【UPDATE】 刚才仔细查了一下mobygames，在《Eschalon: Book I》（Basilisk工作室著名的独立RPG）的Credits里，看到了Reiner Prokein的名字！
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.limboy.com/wp-content/uploads/2011/05/tilexp.png"><img src="http://www.limboy.com/wp-content/uploads/2011/05/tilexp.png"   class="alignnone size-full wp-image-410" style="float:left;margin:0 10px 10px 0" /></a>不论2D还是3D时代，游戏开发总是“美术密集型”的项目，假如把程序比作骨架和器官，把剧情设定和gameplay之类都比作灵魂，那么美工创造出来就是实实在在的血肉，是游戏中绝大部分的“内容”。对于非美工出身的独立游戏创作者，这些“内容”的来源总是一个大难题，当然总有些<a href="http://forum.fr2db.fr/topic17135.html" target="_blank">取巧的题材或设计</a>能绕过这个槛，但是也总能看到那些成功的例子都离不开丰满的视觉内容，甚至是独特的艺术风格，比如iOS平台上最火的那些“小制作”：有<a href="http://roboxstudios.com/grimm/" target="_blank">Grimm</a>的Edward Gorey式维多利亚哥特，有Rolando搭上的<a href="http://cargocollective.com/mikkowalamies" target="_blank">芬兰插画家</a>，还有最近<a href="http://www.swordandsworcery.com/artwork/" target="_blank">Sword &#038; Sworcery EP</a>那“淡淡忧伤”的像素画风……</p>
<p>实际上对那些想要制作游戏的宅男们来说，美工背景有天然优势，程序员离不开心灵手巧的美工，而美工却能不依赖可怜的程序员，这主要是因为程序员们有一种根深蒂固深入骨髓的恶习叫作“抽象”和“复用”，他们总是不甘心只把想要的东西简简单单实现出来，总是忍不住去把其中通用的、不变的、能反复利用的部分提取出来，完善成库、框架、引擎和工具，有极少数头脑发热耳鸣眼花鼻塞手贱腿抽筋的人甚至会继续折腾出一套“不需要编程”就能自由创作的强大工具……在这些资源和技术宅的帮助下，很多美术宅和性幻想达人们都顺畅的踏上了游戏制作之路……可参考<a target="_blank" href="http://zh.wikipedia.org/zh/%E6%AD%A1%E8%BF%8E%E5%8A%A0%E5%85%A5NHK!">《欢迎加入NHK!》</a>里的山崎薫和佐藤，或现实世界里的<a href="http://zh.wikipedia.org/wiki/%E6%AD%A6%E5%86%85%E5%B4%87" target="_blank">武内崇</a>和<a href="http://zh.wikipedia.org/zh-cn/%E5%A5%88%E9%A0%88%E7%A3%A8%E8%8F%87" target="_blank">奈须蘑菇</a>……<span id="more-401"></span></p>
<p>好罢以上都是“技术宅你们伤不起”系列的吐槽，其实不会写程序就像束缚了手脚去爬山，同样很辛苦。我想说的是，相对于代码和软件，可复用的美术资源实在是太稀缺了，如果你也曾经在网上搜寻过免费完整的游戏开发资源，一定体验过那种浪费大量时间仍一无所获的挫折感。</p>
<p>而今天要讲的，是一个站出来挑战这种现状的平凡宅男的故事。</p>
<p>国外有一些独立游戏为了回馈社区，会释出一些自己使用的代码和资源，如果留意过相关的声明，会发现很多开发者都注明“图像来自Reiner Prokein”，其中<a target="_blank" href="http://www.ambardia.com/FreeGraphics/FreeGraphics.html">Ambardia网站</a>上提供下载的那些帖图（tile）资源最壮观最让人惊喜：</p>
<p><a target="_blank" href="http://www.limboy.com/wp-content/uploads/2011/05/Screen-shot-2011-05-02-at-4.11.50-AM.png"><img src="http://www.limboy.com/wp-content/uploads/2011/05/Screen-shot-2011-05-02-at-4.11.50-AM.png"  class="alignnone size-full wp-image-406" style="width:500px" /></a></p>
<p>而这些也都是同一个人创作的。</p>
<p>这个人没有wiki词条，在mobygames上没有介绍，一点名气都没有，但他有一个叫Reiner&#8217;s Tilesets的网站（<a href="http://reinerstileset.4players.de/" target="_blank">旧版</a>，<a href="http://www.reinerstilesets.de" target="_blank">新版</a>），提供更海量的资源，全部是自己绘制，全部以freeware形式提供下载，没有任何好看的许可协议（比如CC-BY或GPL），没有任何限制，允许商业使用，允许随意修改，唯一的要求是你确实用它们做游戏（不准直接转卖），并且在商业作品的Credits名单里要包含他的名字。</p>
<p>那是一个更传奇式的名字，叫作Reiner &#8220;Tiles&#8221; Prokein，他是德国人，一直梦想制作自己的电脑游戏。最开始他不懂编程——他基本上什么都不懂，但他没有放弃，没有畏首畏尾，从99年秋天开始，他决定寻找一种不用编程就能制作游戏的软件。</p>
<p>他找到了前辈ambro的神帖：<a target="_blank" href="http://www.ambrosine.com/resource.php">Ambrosine&#8217;s Game Creation Resources &#038; Classic Game Links</a></p>
<p>他逐个尝试，最后喜欢上<a target="_blank" href="http://zh.wikipedia.org/wiki/RPG%E8%A3%BD%E4%BD%9C%E5%A4%A7%E5%B8%AB">rpgmaker 95</a>，开始制作自己的第一个小型RPG。这个游戏完成了，但从来没有公开过，因为他后来得知破解版的rpgmaker有合法性方面的问题。</p>
<p>在这个过程中，他发现网络上缺乏用于制作游戏的免费图像资源，便开始自己绘制，最初他一个像素一个像素的手绘，接下来他发现了TrueSpace（Caligari公司推出的3D图形和动画渲染工具，现在已经被微软收购，用于虚拟地球项目，可免费下载），开始学习所有跟图像渲染有关的知识。</p>
<p>因为不会编程，Reiner制作游戏的努力始终伴随着挫折感，而学习编程看上去又遥不可及。但他没有放弃，他继续搜寻，又发现了<a href="http://rpgmaker.net/" target="_blank">rpgmaker.net</a>，在这个社区里能找到大量处于beta甚至alpha阶段的游戏制作软件，他开始参与到rpgstudio的开发中，为它创作帖图资源，并且从那个时候起开始建设自己的主页，也就是“Reiner&#8217;s Tilesets”，那是2000年春天。</p>
<p>但是要完成一个像rpgstudio这样的项目，所需时间远超他的想象，而这个项目最后也被废止了。</p>
<p>他仍然想要做游戏，这次他找到了MMF（Multimedia Fusion）的主页，来自法国Clickteam公司的这款软件前身就是著名的《游戏工厂》（TGF），只需要点击和托拽就能完成程序逻辑，还有大量扩展，Reiner觉得他终于找到了自己想要的，全心全意的投入其中。已经是2000年冬天。</p>
<p>2007年，Reiner在主页上更新了自己的近况，七年过去了，他没有拿出什么<a href="http://www.reinerstilesets.de/spiele/" target="_blank">引入注目的游戏</a>，不过他声称在尝试开发3D游戏，他现在主要用3D Gamestudio ，MMF有时也用，这意味着他不再像以前那样惧怕编程了，至少学习了一点lite-C（脚本语言）</p>
<p>2010年，Reiner再次更新，原来过去三年他都在克服某些身体健康方面的问题，从Caligari公司接的一些软件测试工作也耗费了他很多时间，总之他没有完成那个3D游戏，但是跟以往的文字一样，他喜欢在段落的末尾用笑脸代替句号：“<strong>But i never give up, and i don&#8217;t stop dreaming :)</strong>”</p>
<p>2011年春天，Reiner用wordpress重建了自己的tileset网站，没有德国游戏门户4players.de和广告的支持，他必须自己支付服务器费用了，末尾仍然没忘记笑脸：“<strong>But i am more than willing to pay this price :)</strong>”</p>
<p>这个故事还没结束，在99~00年的高潮之后，也许一直都会这么平淡无奇，但不知为什么让我觉得很温暖，忍不住分享一下。</p>
<p><strong>【UPDATE】</strong> 刚才仔细查了一下mobygames，在《Eschalon: Book I》（Basilisk工作室著名的独立RPG）的<a target="_blank" href="http://www.mobygames.com/game/windows/eschalon-book-i/credits">Credits</a>里，看到了Reiner Prokein的名字！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2011/05/02/tiles-legend/feed/</wfw:commentRss>
		<slash:comments>3</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>心中的闹钟和罗盘</title>
		<link>http://www.limboy.com/2011/03/08/clock-and-compass-in-my-heart/</link>
		<comments>http://www.limboy.com/2011/03/08/clock-and-compass-in-my-heart/#comments</comments>
		<pubDate>Mon, 07 Mar 2011 17:49:15 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[土豆网]]></category>
		<category><![CDATA[纯水]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=365</guid>
		<description><![CDATA[
四年前写过《Hero’s come back》，现在又到了要写这种文章的时候，却发现想说的东西跟当初完全一样：
Dakkon：『知道』自己是一条艰苦的道路。
The Nameless One： 知道后，我知道再过不久我要到那里去。时间和命运即将临到，我不会再留在这里。
但是要告别四年的时光，无论如何都需要一个郑重的解释，我年前写过一封farewell letter，就直接帖过来用了=_=，末尾附上我的专用告别歌曲《call me call me》 XD
From: &#8220;Yang,Dexter&#8221;
Date: January 21, 2011 4:58:07 AM GMT+08:00
To: &#8220;Xie,Grant&#8221;
Cc: &#8220;Zhang,feng&#8221;

呃，先自白一下，我在心理上有两个情结：1、最讨厌让别人扫兴。2、最害怕让别人失望。——所以这件事情我一直不想说，不过其实不管怎么拖还是无法避免，拖到年后可能对公司会有损害，所以我觉得去TMD还是赶快告诉人家罢：我在年后就需要离职了～
我觉得张峰应该会觉得很突然，因为刚加入一年左右，可能想象不到我的心境。公司年会里最后上台的十几位有四、五年历史的老员工，也让我非常感动（绝对不是场面话），实际上我也只差3个多月就可以上台了，现在我可以很清晰的回忆起07年，刚毕业和工作满一年，3月份辞职，在家宅一个月，4月中旬开始找工作，4月25日来上海加入土豆。
但我注定成不了那个能上台的人，在我内心里，有一个要求“前进”的闹钟，其实在一年前就开始鸣叫了。实际上我对时间非常敏感，最近几年我一直以这样的心态生活：总觉得自己其实得了绝症，只剩下最后几年时间。因为跟别人不一样，我在22岁之前的人生存在至少七年的空白（就类似三井寿罢），虽然我有一个原则是绝不后悔、绝不否定自己的过去，虽然我觉得那段时间有得有失，是那段时间造就了我现在的人格，形成了我现在做事的方法和态度（感谢互联网）。但必须承认的是：在过去相当漫长的一段时间里，我没有去做我应该做的事情，没有获得我能够获得的东西。所以我已经被束缚的太久了，也已经回归的够晚了，我没有时间可以停留。
内心里还埋藏着一个叫作“初衷”的罗盘。我有一个原则是绝不忘记初衷。忘记初衷相当于失去自我，但实际上人很容易在做事和与人交往过程中忘记原本的梦想和渴望。在土豆的最近几年里，我给人的印象可能就是对技术的专注和热爱，我也确实越来越把目光聚焦在技术本身上面。记得Yuki曾经说过我有很多想法，好像也很久没有那种交流了，库、框架、工具、模式、解决方案、尝试新技术，这些仿佛就是我的全部，每个项目、每个需求对我来说都好像是一个借口，只是为了在开发过程中挖掘、提炼和积累出更好的技术，至于产品本身的价值、意义、甚至体验，我都无法控制，无法影响，于是也就不关心。李戎让我给他们的前端介绍经验，我说的第一句就是“很多优秀的技术都来自失败的产品”。——但这个不是我的本意，而是妥协，技术对我来说只是手段和工具，我的初衷是创造新事物，让别人看、让别人用、让别人喜欢，换句话说，产品才是我的目的，学习技术、磨练技术、追求技术，都是为了创造更好的产品，实现那些以前做不到的事情。就好像一个魔法师，背诵咒语，苦练技巧，只为追求力量，然而为什么要获得力量呢——这个就是他的初衷。
我至今仍觉得土豆是一家很棒的公司，虽然已经物是人非，虽然在扩张过程中出现各种大公司的弊病，但它仍然保留着最好的那些部分（至少在局部范围内），这些优点也是我今后选择工作的标杆。另一方面，土豆的前端技术和前端团队，一直都让我自豪。如今土豆即将IPO，算是走完了一段路。前端的主要产品也基本上都转移到其他人（以前我即使没兴趣没效率，也像强迫症一样把东西都控制在自己手里，这样确实很不好），即便需求仍然繁多，反正我在生产力上占的比例也不大。广告和统计之类的系统都趋于稳定，技术架构的演化和规范虽然没有完成（本来我就不觉得有完成的那天），也一直保持在正确的、有前瞻性的路径上，张峰有足够的能力和执行力去推进，其实如果没有我，他还有更大的空间和自由度。我也很好奇：我留下的代码库有多少部分能保持生命力。我觉得要排除掉资历之类的因素，在“第二系统综合症”的影响下，完全由开发者的实际需求来选择，才能检验出真正有价值的部分。
现在是一个很合适的时候，不论对我还是对公司。需要强调的是，我离开不是因为工资低，这几年来一直有很多机会提供两倍以上的薪资标准，我离开也跟上市前景没关系，我好像要到6月份才能拿到最后1/4的期权，在近期离职应该是有损失的。记得加入土豆几个月之后，Vivian刚走（刚开始感到一点物是人非），有网上的老朋友邀请我去北京创业，当时我的回答是”我喜欢善始善终“，也就是说一切都取决于我自己的节奏和我个人的进展，而不是外界环境的变化，实际上从第一家公司开始，我就习惯了眼前人来人往。我不是被土豆的期权和许诺诱惑了四年，留下只是因为我在土豆想做的事情还没做完。
接下来我准备去北京，连带生活环境生活方式也一起改变，因为我觉得僵化的、习以为常的、缺少未知和期待的生活只是浪费生命。我接下来的工作会在豆瓣，实际上四年前我找工作的时候，是先投给豆瓣，然后才找到土豆——我一直都不算典型的视频网站用户，虽然日常看很多视频，但是我对片源、质量、字幕组乃至发片时间都有很宅的要求，很少在视频网站上看片，只能勉强算是一个youtube用户，所以我本来也不适合开发视频网站的产品（我觉得想从开发者的角度创造好产品，吃自己的狗粮是最重要的），我是Google, Apple和豆瓣的用户，我信仰技术，喜欢技术导向、工程师主导的产品文化，喜欢创新的、能拉近未来的事物，希望能为网络上那些在需求被忽视的情况下，仍然能自发组织起内部体系，创造出网络上大多数新内容新文化的“小众”用户们服务。
如果能完整读到这里其实有点超乎我预料了，也许对他人来说，有价值的信息就到第一段为止，我一向比较自我中心，所以写了过多的个人想法，不过，一方面是我真的很重视土豆同事对我的看法，即使要离开上海，也不希望留下任何误解和不良的影响，另一方面，我也是在梳理自己的内心，我觉得『知道』自己是一件很困难又很重要的事情，向前迈步之前，必须先重新审视自己，搞清楚自己到底是谁。
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;片尾曲的分隔线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
call me call me

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;片头曲的分隔线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
Across the Borderline

]]></description>
			<content:encoded><![CDATA[<p><a href="http://t.sina.com.cn/1650793492/5en1hVjbB1A" target="_blank"><img src="http://www.limboy.com/wp-content/uploads/2011/03/054067702d6b4c76aaf33dbb3fb94d79_7-300x300.jpg" alt="" title="清空后的桌子，临别时可以用这种表情和色彩么～ @ 土豆网上海总部" width="200" height="200"  style="float:left;margin:0 20px 10px 0" /></a></p>
<p>四年前写过<a href="http://www.limboy.com/2007/03/03/herosback/" target="_blank">《Hero’s come back》</a>，现在又到了要写这种文章的时候，却发现想说的东西跟当初完全一样：</p>
<blockquote style="border:0"><p>Dakkon：『知道』自己是一条艰苦的道路。<br />
The Nameless One： 知道后，我知道再过不久我要到那里去。时间和命运即将临到，我不会再留在这里。</p></blockquote>
<p>但是要告别四年的时光，无论如何都需要一个郑重的解释，我年前写过一封farewell letter，就直接帖过来用了=_=，末尾附上我的专用告别歌曲《call me call me》 XD</p>
<p>From: &#8220;Yang,Dexter&#8221;<br />
Date: January 21, 2011 4:58:07 AM GMT+08:00<br />
To: &#8220;Xie,Grant&#8221;<br />
Cc: &#8220;Zhang,feng&#8221;<br />
<span id="more-365"></span><br />
呃，先自白一下，我在心理上有两个情结：1、最讨厌让别人扫兴。2、最害怕让别人失望。——所以这件事情我一直不想说，不过其实不管怎么拖还是无法避免，拖到年后可能对公司会有损害，所以我觉得去TMD还是赶快告诉人家罢：我在年后就需要离职了～</p>
<p>我觉得张峰应该会觉得很突然，因为刚加入一年左右，可能想象不到我的心境。公司年会里最后上台的十几位有四、五年历史的老员工，也让我非常感动（绝对不是场面话），实际上我也只差3个多月就可以上台了，现在我可以很清晰的回忆起07年，刚毕业和工作满一年，3月份辞职，在家宅一个月，4月中旬开始找工作，4月25日来上海加入土豆。</p>
<p>但我注定成不了那个能上台的人，在我内心里，有一个要求“前进”的闹钟，其实在一年前就开始鸣叫了。实际上我对时间非常敏感，最近几年我一直以这样的心态生活：总觉得自己其实得了绝症，只剩下最后几年时间。因为跟别人不一样，我在22岁之前的人生存在至少七年的空白（就类似三井寿罢），虽然我有一个原则是绝不后悔、绝不否定自己的过去，虽然我觉得那段时间有得有失，是那段时间造就了我现在的人格，形成了我现在做事的方法和态度（感谢互联网）。但必须承认的是：在过去相当漫长的一段时间里，我没有去做我应该做的事情，没有获得我能够获得的东西。所以我已经被束缚的太久了，也已经回归的够晚了，我没有时间可以停留。</p>
<p>内心里还埋藏着一个叫作“初衷”的罗盘。我有一个原则是绝不忘记初衷。忘记初衷相当于失去自我，但实际上人很容易在做事和与人交往过程中忘记原本的梦想和渴望。在土豆的最近几年里，我给人的印象可能就是对技术的专注和热爱，我也确实越来越把目光聚焦在技术本身上面。记得Yuki曾经说过我有很多想法，好像也很久没有那种交流了，库、框架、工具、模式、解决方案、尝试新技术，这些仿佛就是我的全部，每个项目、每个需求对我来说都好像是一个借口，只是为了在开发过程中挖掘、提炼和积累出更好的技术，至于产品本身的价值、意义、甚至体验，我都无法控制，无法影响，于是也就不关心。李戎让我给他们的前端介绍经验，我说的第一句就是“很多优秀的技术都来自失败的产品”。——但这个不是我的本意，而是妥协，技术对我来说只是手段和工具，我的初衷是创造新事物，让别人看、让别人用、让别人喜欢，换句话说，产品才是我的目的，学习技术、磨练技术、追求技术，都是为了创造更好的产品，实现那些以前做不到的事情。就好像一个魔法师，背诵咒语，苦练技巧，只为追求力量，然而为什么要获得力量呢——这个就是他的初衷。</p>
<p>我至今仍觉得土豆是一家很棒的公司，虽然已经物是人非，虽然在扩张过程中出现各种大公司的弊病，但它仍然保留着最好的那些部分（至少在局部范围内），这些优点也是我今后选择工作的标杆。另一方面，土豆的前端技术和前端团队，一直都让我自豪。如今土豆即将IPO，算是走完了一段路。前端的主要产品也基本上都转移到其他人（以前我即使没兴趣没效率，也像强迫症一样把东西都控制在自己手里，这样确实很不好），即便需求仍然繁多，反正我在生产力上占的比例也不大。广告和统计之类的系统都趋于稳定，技术架构的演化和规范虽然没有完成（本来我就不觉得有完成的那天），也一直保持在正确的、有前瞻性的路径上，张峰有足够的能力和执行力去推进，其实如果没有我，他还有更大的空间和自由度。我也很好奇：我留下的代码库有多少部分能保持生命力。我觉得要排除掉资历之类的因素，在“第二系统综合症”的影响下，完全由开发者的实际需求来选择，才能检验出真正有价值的部分。</p>
<p>现在是一个很合适的时候，不论对我还是对公司。需要强调的是，我离开不是因为工资低，这几年来一直有很多机会提供两倍以上的薪资标准，我离开也跟上市前景没关系，我好像要到6月份才能拿到最后1/4的期权，在近期离职应该是有损失的。记得加入土豆几个月之后，Vivian刚走（刚开始感到一点物是人非），有网上的老朋友邀请我去北京创业，当时我的回答是”我喜欢善始善终“，也就是说一切都取决于我自己的节奏和我个人的进展，而不是外界环境的变化，实际上从第一家公司开始，我就习惯了眼前人来人往。我不是被土豆的期权和许诺诱惑了四年，留下只是因为我在土豆想做的事情还没做完。</p>
<p>接下来我准备去北京，连带生活环境生活方式也一起改变，因为我觉得僵化的、习以为常的、缺少未知和期待的生活只是浪费生命。我接下来的工作会在豆瓣，实际上四年前我找工作的时候，是先投给豆瓣，然后才找到土豆——我一直都不算典型的视频网站用户，虽然日常看很多视频，但是我对片源、质量、字幕组乃至发片时间都有很宅的要求，很少在视频网站上看片，只能勉强算是一个youtube用户，所以我本来也不适合开发视频网站的产品（我觉得想从开发者的角度创造好产品，吃自己的狗粮是最重要的），我是Google, Apple和豆瓣的用户，我信仰技术，喜欢技术导向、工程师主导的产品文化，喜欢创新的、能拉近未来的事物，希望能为网络上那些在需求被忽视的情况下，仍然能自发组织起内部体系，创造出网络上大多数新内容新文化的“小众”用户们服务。</p>
<p>如果能完整读到这里其实有点超乎我预料了，也许对他人来说，有价值的信息就到第一段为止，我一向比较自我中心，所以写了过多的个人想法，不过，一方面是我真的很重视土豆同事对我的看法，即使要离开上海，也不希望留下任何误解和不良的影响，另一方面，我也是在梳理自己的内心，我觉得『知道』自己是一件很困难又很重要的事情，向前迈步之前，必须先重新审视自己，搞清楚自己到底是谁。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;片尾曲的分隔线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>call me call me</p>
<p><embed src="http://www.tudou.com/v/Z9b4J5HHR9w/&#038;rpid=2777994/v.swf" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="480" height="400"></embed></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;片头曲的分隔线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Across the Borderline</p>
<p><embed src="http://www.tudou.com/v/8O61sOzT_CQ/&#038;rpid=2777994/v.swf" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="480" height="400"></embed></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2011/03/08/clock-and-compass-in-my-heart/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>《通用JS时代的模块机制和编译工具》的幻灯片和……剧本……</title>
		<link>http://www.limboy.com/2010/12/19/module-and-compiler-for-common-js/</link>
		<comments>http://www.limboy.com/2010/12/19/module-and-compiler-for-common-js/#comments</comments>
		<pubDate>Sat, 18 Dec 2010 18:53:24 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[代码]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=356</guid>
		<description><![CDATA[昨天在D2前端技术论坛上的演讲居然很顺利，因为是第一次演讲，我本来是完全没信心的，一个月前头脑发热答应了这件事，但是拖到最后三天才开始准备，演讲前一天只睡了4个小时，因为睡觉前刚赶出幻灯片的最后一个章节，比这些更可怕的是，本来我想逃避“口头表达”，希望演讲就是用slide说话、演示几个DEMO、把控制台和编辑器投影到大屏幕上秀给人们看……所以我在倒数第二天的时候通宵做幻灯片，图文并茂五颜六色各种效果全用上（现学mac上的keynote），没睡觉，白天在公司里试讲，只面对五六个人，却一个字都说不出来，不知道怎么即兴讲解幻灯片（特别是代码片段），连直接读幻灯片上的文字都做不到……当时便有一种必死无疑引颈就戮人生终点就在后天的感觉。
因此我做出一个艰难的决定——把演讲变成念台词，不但要准备slide，还要准备完整的讲稿，每一页slide时要说什么，有没有很难发音的词汇，什么时候停顿，点几下鼠标，都先做好万全的计划。最后一天全在忙这个，还测试了如何把ipad藏在讲台上念稿，好像找回了当年高数考试前天晚上策划作弊的亢奋感觉。
结果昨天上台时一切顺利，80页的slide刚好在50分钟左右讲完，最后一个章节没有来得及准备讲稿，却即兴的讲了很多，最后QA环节回答问题时甚至说得不想停下……现在想想，那天试讲主要的问题其实是没睡觉，缺水，颅内温度很高，大脑某些部分罢工了……
当然也有遗憾，不是会场比较小（人多了不知道会不会紧张），而是我在slide里准备的笑点……比如绝望先生的配图……没有产生任何效果。感觉演讲这种事情如果要产生最大的效果，还是更依赖情感交流，而不是内容交流……
另外我回家之后发现标题是败笔，很多人可能会把“CommonJS时代的模块和工具”理解成“CommonJS的模块和工具”，以为我要讲CommonJS……这可是前端论坛啊，其实直接叫“通用JS时代的模块和工具”就行了……
以下是今天分享的主题的slide和……龌龊的剧本（原封不动的草稿）……这样真好，连视频都不用等了，不过剧本缺最后关于工具的那个章节。另外虽然我写了这么多关于演讲的感想，但我还是希望这篇blog的反馈是关于JS模块和编译工具的……
PS: OzJS这个名字来自绿野仙踪的奥兹国，迪斯尼正在拍“The Great And Powerful Oz”……
通用JS时代的模块机制和编译工具
View more presentations from Dexter Yy.

1
大家好，今天我要分享的主题是，CommonJS时代的模块机制和编译工具
其实最早我发给小马的主题，是叫做“后浏览器时代的JavaScript——通用模块和辅助构建”
不过后来担心那个标题有点晦涩可能引起误解，
以为是讲软件工程啊流程啊方面的东西……所以就改成现在这样
不过还是有点长有点复杂，不知道大家看到这个标题会怎么想的
2
嗯可能有些人是这么想的……（点）(回头看PPT)
3
嗯不过接下来就会产生疑问……
（点）（回头看观众，停顿）
我想问现场一个问题，有多少了解，或者听说过CommonJS?
4
除了这个问题（点）
可能还会有人对时代这个词感觉比较奇怪
5
最后可能有人要问，（点）为什么要讨论模块和工具，
因为这个不像前端性能啊什么的，是大家都关心的热点
所以我觉得今天这个主题有必要先来作一下回顾
6
先来看看前端日常工作中存在的问题
（点）……这是一张以前在土豆办公室拍的照片，
中间是我，友下角有上上次D2做分享的李戎同学
这张照片看上去蛮河蟹的，其实这些人不是在做前端日常工作，而是在上班时间打游戏
7
先来回顾一下现状
（点）嗯，因为我比较紧张，可能口头表达的不太清楚，请大家直接看幻灯片上的文字
比如拿土豆网来举例，土豆从06年开始，做了一些比较之后开始使用jQuery
而到了07年，我们开始逐步积累自己的代码库
我们并没有逐步替换jQuery，但是也没有采用jQuery的结构和扩展方式去构建代码库
实际上就是把jQuery当作JS的一种内部DSL来用，DSL就是领域语言的意思
到现在也封装出了很多东西，比如常用的编程模式，web应用的模式，工具库，UI组件，等等
平时也注意把需求尽可能的抽象，让代码尽可能的可以复用，也就是不开发重复的东西
（点）这个好像是去年做的一张代码库的结构图，
现在已经过时了，不过可以看到代码单元还是蛮多的
8
9
接下来我们看一下这种现状带来的问题
（点）因为虽然有很多流行的库和框架，但是并没有真正的主流
于是不同的公司、不同的团队、不同的项目，
就可能会有各自不同的代码组织结构，不同的接口风格
这样积累下的代码就有很强的依赖性，
只能在特定项目、特定的公司里使用，或者只能在特定的团队里得到复用
就是说虽然我们重视代码复用，但是事与愿违，代码经常难以在不同项目不同团队之间迁移
难以在不同项目不同团队之间得到管理维护
如果有了独创性的东西，也很难分享到外部，很难得到广泛传播
最后的结果就是大家都在闭门造车轮。
10
来看看第二个现状（点）
比如土豆的前端代码在上线前要经过好几个环境
有开发环境，测试环境，还有跟线上数据完全一致的测试环境
最后这个测试环境中使用的静态文件（比如JS，CSS）都跟线上一样是来自CDN的，
修改后在CDN中同步要等10几分钟，在页面里生效又要等几分钟
每次做了修改，就算是简单的bugfix，也要经历很多环节才能发布上线
（点）这是土豆网首页HTML底部的截图
可以看到上面的红圈是系统自动生成的静态文件版本号，用来控制浏览器缓存
下面这行注释后面的代码是从UI文件服务器上自动抓取嵌入到页面里的
这个首页本身也是静态化的
11
这些流程也带来一些问题(点)
我一直很反对的是，在改进过程的时候损害开发者的利益
如果过程改进增加了开发成本，不应该觉得是理所当然的
而是说明有某些地方没做好，或者缺少了某些东西，比如工具
好的过程应该能隐藏复杂性，减少出错机会。
同时这些环节也对代码的管理提出更高要求，
比如有些代码需要独立的测试，每次修改也要缩小影响范围，
很多东西都依赖代码单元和文件的粒度。
12
第三个现状
这个应该不用解释，上周我刚参加过北京的velocity性能大会
可以看到现在大家对前端性能都是很重视的。
13
这里存在的问题是跟上一条相关的，
比如最简单的例子，为了方便代码的调试维护，我们会希望把JS文件拆分的很细
比如一个UI插件，希望它是独立的文件。
但是性能优化又要求减少页面里的文件请求数
为了尽可能利用浏览器缓存，可能还需要多个页面共享同一个大文件
这两方面的希望是互相矛盾的
14
刚才回顾了三个方面
他们都对同一个问题提出了要求
（点）就是JS代码本身的组织管理和使用
15
解决的途径之一，就是标题里提到的两个东西
16
这个标题可以拆成三部分
后两个是手段，第一个是背景，先来看一下这个背景
17
在这里我把CommonJS翻译成通用JS，接下来就可以看到为什么要叫通用
18
CommonJS是目前广泛流行的一套API规格
不叫它标准是因为它并不是来自像W3C,ECMA这样的官方组织
而是业界自发组织起来，发展出的项目，而且也正在在逐步成为一个事实标准
事实标准这个词是来自拉丁文的修辞，
意思是法律没有规定，但是“在事实上”或者“执行上”是怎样做
（点）它的反义词则是指有明确的法律，但是人门在现实中不会遵守
说到这两个词我们可以很容易的联想到HTML5和XHTML2，一个典型例子
这个民间项目关注的是更广义的JS开发，不止是浏览器
它的目标是建设一个JS的生态系统
19
有人可能会说现在的JS难道没有生态系统么
但是既然业界有这个目标，就说明即使有生态系统，也存在一些问题
当然其中一个问题是JS缺少服务器端开发需要的API，不过这个不是今天的重点
（点）python,ruby跟JS一样是动态语言，也非常流行，他们有内置的标准库
特别是python，有一个著名的宣传口号是“内置电池”，因为标准库非常全面
除了标准库，他们还有一个更庞大的由社区建立的代码库，其中CPAN是最早最有名的
很多人就是因为这个CPAN的存在，才会选择这个语言或者无法摆脱这个语言
JS我们知道也有大量的开源代码，但对你来说并不是每个代码都能用
比如有的是JQUERY插件，有的是YUI插件
还有一些独立的库即使很小，也必须包含重复的功能，因为它不能依赖其他东西
另外那些在浏览器里运行的代码拿到服务器端当然就更没法用了
20
比如这个例子，是我用Python写的翻墙工具，代码的第一行就是在导入标准库
包括操作系统相关，文件读写，正则表达式
下面几行我又使用了几个第三方代码库，其中的mako是一个HTML模板引擎
要获取这个库，我只需要使用Python的包管理工具
一个命令就能查找、下载、安装它自身和它依赖的其他库，而且都是最新版本
这些东西对开发带来了很大的便利，大幅提高开发效率。
21
回到CommonJS, 最早是在09年初，这个叫kevin的人建立了讨论组，最早其实是叫ServerJS讨论组
他当时写了一篇文章叫《服务器端JS需要什么》，所以最初的推动力是来自服务器端开发的需求
因为如果只局限在浏览器的特殊文化里，不接触其他语言，很多问题和需求可能都察觉不到
这个人是Mozilla的开发者工具团队的工程师，这个团队的创建和它发起的项目都很有名的
比如skywriter可能有人听说过，是一个用JS开发的在线版本编辑器
他好像是turbogears项目的创始人，turbogears是一个python的web开发框架
国外著名的开源项目网站sourceforge的新版就是用它开发的
22
Commonjs本身不提供任何具体实现，它只是约定一套东西，由兼容它的项目去实现，
按照这种约定开发出来的JS应用和模块，不做修改就可以在这些兼容COMMONJS的平台上运行
而我们最需要关注的是它对于模块的约定，后面会介绍具体的代码怎么写
23
接下来看一下广义的通用JS
其实我是借用这个词来概括当前的趋势和背景
它包含两层意思，一方面是在更多领域更多环境里需要使用JS，就是说JS本身通用了
另一方面，JS代码也需要变得通用。
24
我们来看几个例子
25
首先最自然的延伸，浏览器扩展
firefox是最早用JS开发扩展的浏览器，因为实际上它浏览器本身的界面也大量使用JS
但是以前的firefox扩展开发门槛还是很高的，比如要学习XUL，要使用C++的API
现在新的jetpack SDK不但提供了高层的JS API和测试工具，打包工具
还提供了兼容CommonJS的模块机制，让扩展开发轻松了很多
26
比如这是我以前用jetpack SDK的早期版本开发的工具软件，可以算一种自动化测试工具
简单概括就是一个爬虫，提供一个网址入口，它可以顺着超链接一路爬下去
找出所有相连的网页，并且对每一个网页应用你自定义的脚本，最后输出脚本结果的报表
因为这个不是主题而且有时间关系就不演示了
来看看它的代码，其中有一部分界面相关的JS还是以前firefox扩展的写法
不用解释就能看出代码很丑陋吧
这个是新的写法，比刚才清晰多了，可以看到我导入了几个API，每个API都是一个模块
request模块就是AJAX，pageworker相当于iframe，还导入了我自己的库TUI
27
除了firefox，其他浏览器也都开始支持用JS开发扩展，目前最火的当然是google的chrome
我这里给出一个safari扩展的例子，因为还没时间移植到chrome上
这个扩展完全用JS,HTML5和CSS3开发，只用到一张图片，UI和动画效果都是CSS3实现的
开发的时候非常方便，不过也有不爽的地方
就是它的JS没有模块化设计，apple提供的API很少，还做了很多麻烦的限制
其实我一直觉得chrome的扩展开发虽然比firefox简单，但是很难开发很强大很给力的应用
28
再来跳出浏览器，看看移动平台上的例子
(点)比如nokia目前基于厚望的QT Quick，QT本来是一个C++的GUI库
因为这一点有很多不喜欢C++的人不愿意用它，为了讨好开发者
QT quick包含QML，可以用JS和类似JS的声明式语言来快速开发手机或平板电脑上的应用
29
当然更有名的是webOS，应该多数人都听说过了
这个移动操作系统一开始就要求所有软件都用JS开发
新的2.0系统更进一步集成了nodejs，后面会做介绍，它也是CommonJS的兼容实现
也就是说我刚才给firefox扩展开发的JS模块可以直接拿到这里使用
30
除了新的移动平台，电脑桌面上其实也有很多GUI库使用了JS
这里举一个比较新的国产的例子，是豆瓣的洪强宁开发的
这里的ONERING是指魔戒里的一枚戒指统御众戒
所以这个名字意思应该是说同一种JS技术可以开发多种界面
不但能开发web上的，也可以开发桌面上的
我给他提过一个建议, 最好能兼容COMMONJS
31
下一个例子是今年欧洲JS大会上一个演示，这个演示的幻灯片里包含几个饼图
黄色是客户端，蓝色是服务器，紫色是嵌入式
可以看到09年第一届JS大会上的分享100%是关于客户端开发的
到了下一届有1/5是关于JS在服务器的应用，再一下届变成一半比例
到了这一届甚至出现了嵌入式开发，作者希望到下一届能各占1/3
32
实际上这10%的嵌入式内容是指作者自己的分享
他们希望能用JS控制一种在国外非常流行的开源硬件平台
33
这个视频演示了他们使用nodejs开发server，
然后在ipad上通过web界面里的JS代码遥控硬件设备
因为时间关系不在这里播放了……
34
最后的例子当然是服务器端的JS了
目前的绝对主流就是nodejs
传统的服务器端JS都会让人觉得很不靠谱，跟ASP之类的东西差不多。
nodejs的靠谱之处在于它的出发点不是为了在服务器和浏览器用同一种语言做开发
这种需求只是一种个人喜好，不一定是最好的选择，也不一定有实用价值。
nodejs想要推广的是基于事件的异步编程
这种编程模式对我们前端开发者来说好像是天经地义的
因为我们已经习惯了浏览器里的各种DOM事件和匿名的回调函数，
AJAX请求，图片加载，也都是异步的
但是对服务器上的开发者来说这是一种需要额外支持，需要努力去适应的模式
JS天生就提供这种支持，而这种编程模式的好处
就是可以适应大规模并发和实时性非常高的服务器应用
比如像webQQ这样的东西。
第三条里提到的erlang (erlan) 是以并发性能著称的函数式编程语言
Nodejs被拿来跟它比较，就算比不过，也说明Nodejs性能有竞争力
35
具体的例子因为时间关系就算了，重点是想强调一下它的模块数量
/*
这里如果是乔布斯演讲，幻灯片上应该会掉下一个很大的550
*/
github的一个wiki页面上收录了很多Nodejs的第三方模块
我随便抓取了一下数量，有550个以上，涉及各种功能。
对于一个发布刚好一年的项目来说这应该算蛮惊人的。
36
回头来看浏览器上的JS，跟刚才的一对比就会感觉通用的模块太少
这里说的通用还仅仅只是在前端，在不同项目不同团队不同公司之间通用
前端的JS社区很分散，jquery有jquery的社区，YUI有YUI的
虽然有一些互相借鉴但是还是有很多东西只在内部传播和使用
外部的开发者是不了解的，也不会去用
而且缺少有利于分享的基础设施，这里说的基础设施不是指开源网站
当然那个也算，这里要说的是更底层的设施
37
其中之一就是模块机制，也就是这次分享的第三个部分
38
先放大视野，看一下其他语言里的模块是什么样子
（点）先请出刚才提到过的python, python代码很简洁，相信没用过的人也看的懂
（点）这里一个框表示一个代码文件
这个文件导入了模块B，然后调用模块B里的say方法
模块B的用法就像这个文件里的一个普通对象一样
（点）模块B定义了两个变量和刚才调用过的say函数
而这个函数里又调用了一个叫cat的类，生成猫的实例，让它叫一下
但是模块B文件里并没有cat类的定义，看第一行可以知道这个类是从模块A里导入进来的
（点）模块A文件里也定义了a变量，但是因为没有声明导入它，
所以不会覆盖模块B文件里定义的a
这个就是python里模块的基本用法
从中我们可以总结几条python模块的特性
39
可以发现这些特性都符合开发者的直觉，也符合开发的需要，
对模块的开发和使用都很有好处
这里没时间演示其他语言的模块，比如ruby, actionscript3，但是这些特性都差不多的
看了这个列表, 我们还可以发现另一件事情
（点）浏览器里的JS不符合其中任何一条
40
可以对比一下：
JS存在全局作用域，不同文件会共享同一个全局命名空间（点）
所有文件一开始都会解析执行（点）
没有相关的声明语句，只能用异步加载文件的方式模拟导入的效果（点）
导入之后不管你想不想要，那个文件里的东西会全部注入到当前的命名空间里（点）
可能隐式的导入很多全局变量，覆盖或修改当前的内容（点）
为了避免这种情况，模块文件就不能采用最自然最简单的写法，比如直接定义变量和函数
而必须把所有东西都放到一个特殊的命名空间下面，比如jquery.js就是这样
JS文件自身也不包含依赖信息，如果有打包合并之类的操作
我们可能会把依赖信息写在另外的配置文件里（点）
41
我们来看看JS的代码通常是怎样组织的
（点）这个是最传统的写法，现在仍然有人在用
（点）某个网站的HTML截图，文件的顺序就是代码的依赖关系
（点）这个已经算是比较新的方法，用工具自动合并这些文件
但是如果这张图里的文件还是刚才那些文件，本质上是没有区别的，仍然依赖从上到下的顺序
42
因为这些传统，我们对浏览器端的特殊文化已经习以为常，见怪不怪了
可能没有觉得有什么不对，但是时间长了会觉得很麻烦和低效
不过最后这一条起到了一定的正面推动作用
为了改善前端性能，很多开发者开始尝试封装出一些工具
43
我把它们称作脚本加载器
44
比如这个例子，它的API提供了串行和并行加载脚本文件的功能
最大的特点应该算是用类似jquery的链式调用风格来实现串行加载
（点）（点）
45
这是另一个库，API风格有很大不同，我们看看有没有新功能
（点）（点）所以这里的并行下载，按依赖关系执行，
只是用预加载技术模拟出来的效果，实际上会请求多次
而且依赖关系仍然取决于前后顺序（点）（点）（点）
本质上还上一个库是一样的
46
最后一个例子是土豆自己的（点）(点）
JS文件名里包含在版本号是在HTML里自动生成的
（点）（点）
(点）虽然当时命名成module，本质上还是脚本加载器
47
除了大同小异的脚本加载器，我们还习惯了另一种代码组织方式
（点）这种模块模式同样也是为了克服之前列举的JS的缺陷
刚才列举的这些东西虽然有帮助，但是跟其他语言原生的模块支持相比，仍然差距很大
48
于是有人提出了更本质上的问题：JavaScript需要模块！
（点）这个名字叫戴夫赫尔曼的人并不是随便说说而已
（点）他的条件很好，跟JS创始人在一起工作，而且是TC39的成员，
TC39是负责制定下一代JS标准的小组
所以他直接发起了一个新提案，希望给JS语言加入simple module的功能
49
第二个链接是他在TC39会议上做的演讲，描述了simple module的目标和初步设计
下面这个N开头的东西是mozilla开发的实验性JS引擎，可以快速加入新功能做测试
50
简单来说他设想的simple module就是这个样子
增加了四个重要的声明语法，虽然语法很简单，但是有了这四个词之后，
JS就完全具备了跟python模块一样强大的功能
51
刚才的代码没看的明白也没关系，因为第一，它目前还只是一个稻草人提案，
就是说这个提案的功能是吸引更多人来讨论它的缺点，从而产生新的和更好的方案
第二，它是一种新引入的语法，跟CommonJS不一样，CommonJS是要用现有的语法去改善JS开发
而simple module的初衷是直接改善JS语言本身，
ES5的邮件列表里有一个相关的讨论，JS创始人布兰登也发表了意见
52
虽然短时间内不能用，但是可以先借鉴一下这个提案里列举的目标
我们是否能利用现有的JS语法和功能，来追求这些目标，实现比较理想的模块机制呢
53
之前好几次提到CommonJS的模块，现在终于轮到讨论它了
54
先请出之前展示过的爬虫程序，在介绍firefox扩展的时候，提到过它实现了CommonJS的模块
这里给出的两段代码分别来自同一个模块文件的顶部和底部（点）
圈出的部分就是CommonJS模块的主要特征（点）
55
（点）把之前python模块的示例代码，直接改成commonjs的写法（点）（点）功能特性完全一致
区别只是导入模块时不是用声明语句，而是调用require函数
可以说CommonJS满足了之前提出的所有要求，
在不引入新语法的前提下，实现了比较理想的模块机制
可惜这种代码完全没办法在浏览器里使用，障碍有两个：
第一，网页里不同JS文件之间全局命名空间是共享，而服务器端CommonJS里每个文件都是独立的
第二，require函数是阻塞式的，读取完模块文件，并返回模块对象之前，不会执行后续的代码
在服务器上这是很自然的，但是在浏览器里，读取文件是异步操作，阻塞会影响页面的交互
所以没办法、也不能让require函数阻塞代码的执行
56
于是现在要解决的问题转变成了这个了
不过在讲解决方案之前，我要先插播两页
57
58
59
嗯接下来开始介绍浏览器里的CommonJS兼容实现：RequireJS
它的开发者比我条件好，近水楼台先得月……
它定义了两个方法，require和define，其中define是关键设计，
已经成为了新的CommonJS规范，叫做异步模块
60
来看看所谓异步模块是什么样的
（点）还是跟之前Python模块和CommonJS模块的示例代码保持一致（点）（点）
可以看到require变成异步调用，第二个参数是匿名函数，
这个函数的作用域相当于模块文件的顶层作用域
作用域里的代码可以跟服务器端CommonJS完全一致，
包括使用阻塞式的require，用exports生成模块对象
这个作用域里也可以直接采用传统的模块模式的写法，用return来生成模块对象
依赖的模块会被转变成模块对象，通过函数参数传入
define函数具备require的所有功能，同时提供了定义新模块的能力，
当模块代码位于独立的文件里
比如像这里的模块A，模块名称的参数可以省略，直接绑定到文件名
61
异步模块的require和define还有一种衍生的用法，就是用来请求JSONP接口
define不但支持传入函数，也可以直接传入一个对象作为模块对象
用这个方法请求JSONP的好处是不用担心callback污染全局命名空间，
还可以起到缓存的效果，因为模块文件只会加载一次
62
总结一下异步模块的优点
63
刚才说过requireJS算是异步模块的一个官方实现，
不过相比之下我更喜欢自己实现的oz.js
一个原因是代码更少更简单，另一个原因是我对define函数的用法有不同的意见
requirejs仍然采用服务器端的做法，把模块名直接等同于文件地址，
但是前端开发中很少有这么理想的情况
而对于要下载的JS文件不需要做静态的声明，只在运行时里检查，也会产生很多不便
64
对照代码看看oz.js的def方法有什么不同
65
内部细节只强调几个功能上的问题
oz.js本身包含了前面提到的脚本加载器的所有功能，但是只会用到并行加载，
因为模块文件之间没有依赖关系。
66
在模块部分的最后引用一下这句话：“让代码更容易分享，大家就会分享更多的代码”。
]]></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;"  />昨天在<a href="http://www.d2forum.org/d2/5/" target="_blank">D2前端技术论坛</a>上的演讲居然很顺利，因为是第一次演讲，我本来是完全没信心的，一个月前头脑发热答应了这件事，但是拖到最后三天才开始准备，演讲前一天只睡了4个小时，因为睡觉前刚赶出幻灯片的最后一个章节，比这些更可怕的是，本来我想逃避“口头表达”，希望演讲就是用slide说话、演示几个DEMO、把控制台和编辑器投影到大屏幕上秀给人们看……所以我在倒数第二天的时候通宵做幻灯片，图文并茂五颜六色各种效果全用上（现学mac上的keynote），没睡觉，白天在公司里试讲，只面对五六个人，却一个字都说不出来，不知道怎么即兴讲解幻灯片（特别是代码片段），连直接读幻灯片上的文字都做不到……当时便有一种必死无疑引颈就戮人生终点就在后天的感觉。</p>
<p>因此我做出一个艰难的决定——把演讲变成念台词，不但要准备slide，还要准备完整的讲稿，每一页slide时要说什么，有没有很难发音的词汇，什么时候停顿，点几下鼠标，都先做好万全的计划。最后一天全在忙这个，还测试了如何把ipad藏在讲台上念稿，好像找回了当年高数考试前天晚上策划作弊的亢奋感觉。<span id="more-356"></span></p>
<p>结果昨天上台时一切顺利，80页的slide刚好在50分钟左右讲完，最后一个章节没有来得及准备讲稿，却即兴的讲了很多，最后QA环节回答问题时甚至说得不想停下……现在想想，那天试讲主要的问题其实是没睡觉，缺水，颅内温度很高，大脑某些部分罢工了……</p>
<p>当然也有遗憾，不是会场比较小（人多了不知道会不会紧张），而是我在slide里准备的笑点……比如绝望先生的配图……没有产生任何效果。感觉演讲这种事情如果要产生最大的效果，还是更依赖情感交流，而不是内容交流……</p>
<p>另外我回家之后发现标题是败笔，很多人可能会把“CommonJS时代的模块和工具”理解成“CommonJS的模块和工具”，以为我要讲CommonJS……这可是前端论坛啊，其实直接叫“通用JS时代的模块和工具”就行了……</p>
<p>以下是今天分享的主题的<a href="http://www.slideshare.net/dexter_yy/js-6228773" target="_blank">slide</a>和……龌龊的剧本（原封不动的草稿）……这样真好，连视频都不用等了，不过剧本缺最后关于工具的那个章节。另外虽然我写了这么多关于演讲的感想，但我还是希望这篇blog的反馈是关于JS模块和编译工具的……</p>
<p>PS: <a href="https://github.com/dexteryy/OzJS" href="_blank">OzJS</a>这个名字来自绿野仙踪的奥兹国，迪斯尼正在拍“The Great And Powerful Oz”……</p>
<div style="width:425px" id="__ss_6228773"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/dexter_yy/js-6228773" title="通用JS时代的模块机制和编译工具">通用JS时代的模块机制和编译工具</a></strong><object id="__sse6228773" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=module-and-compiler-for-common-101218105758-phpapp02&#038;rel=0&#038;stripped_title=js-6228773&#038;userName=dexter_yy" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse6228773" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=module-and-compiler-for-common-101218105758-phpapp02&#038;rel=0&#038;stripped_title=js-6228773&#038;userName=dexter_yy" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/dexter_yy">Dexter Yy</a>.</div>
</div>
<p>1<br />
大家好，今天我要分享的主题是，CommonJS时代的模块机制和编译工具<br />
其实最早我发给小马的主题，是叫做“后浏览器时代的JavaScript——通用模块和辅助构建”<br />
不过后来担心那个标题有点晦涩可能引起误解，<br />
以为是讲软件工程啊流程啊方面的东西……所以就改成现在这样<br />
不过还是有点长有点复杂，不知道大家看到这个标题会怎么想的</p>
<p>2<br />
嗯可能有些人是这么想的……（点）(回头看PPT)</p>
<p>3<br />
嗯不过接下来就会产生疑问……<br />
（点）（回头看观众，停顿）<br />
我想问现场一个问题，有多少了解，或者听说过CommonJS?</p>
<p>4<br />
除了这个问题（点）<br />
可能还会有人对时代这个词感觉比较奇怪</p>
<p>5<br />
最后可能有人要问，（点）为什么要讨论模块和工具，<br />
因为这个不像前端性能啊什么的，是大家都关心的热点<br />
所以我觉得今天这个主题有必要先来作一下回顾</p>
<p>6<br />
先来看看前端日常工作中存在的问题<br />
（点）……这是一张以前在土豆办公室拍的照片，<br />
中间是我，友下角有上上次D2做分享的李戎同学<br />
这张照片看上去蛮河蟹的，其实这些人不是在做前端日常工作，而是在上班时间打游戏</p>
<p>7<br />
先来回顾一下现状<br />
（点）嗯，因为我比较紧张，可能口头表达的不太清楚，请大家直接看幻灯片上的文字<br />
比如拿土豆网来举例，土豆从06年开始，做了一些比较之后开始使用jQuery<br />
而到了07年，我们开始逐步积累自己的代码库<br />
我们并没有逐步替换jQuery，但是也没有采用jQuery的结构和扩展方式去构建代码库<br />
实际上就是把jQuery当作JS的一种内部DSL来用，DSL就是领域语言的意思<br />
到现在也封装出了很多东西，比如常用的编程模式，web应用的模式，工具库，UI组件，等等<br />
平时也注意把需求尽可能的抽象，让代码尽可能的可以复用，也就是不开发重复的东西<br />
（点）这个好像是去年做的一张代码库的结构图，<br />
现在已经过时了，不过可以看到代码单元还是蛮多的</p>
<p>8</p>
<p>9<br />
接下来我们看一下这种现状带来的问题<br />
（点）因为虽然有很多流行的库和框架，但是并没有真正的主流<br />
于是不同的公司、不同的团队、不同的项目，<br />
就可能会有各自不同的代码组织结构，不同的接口风格<br />
这样积累下的代码就有很强的依赖性，<br />
只能在特定项目、特定的公司里使用，或者只能在特定的团队里得到复用<br />
就是说虽然我们重视代码复用，但是事与愿违，代码经常难以在不同项目不同团队之间迁移<br />
难以在不同项目不同团队之间得到管理维护<br />
如果有了独创性的东西，也很难分享到外部，很难得到广泛传播<br />
最后的结果就是大家都在闭门造车轮。</p>
<p>10<br />
来看看第二个现状（点）<br />
比如土豆的前端代码在上线前要经过好几个环境<br />
有开发环境，测试环境，还有跟线上数据完全一致的测试环境<br />
最后这个测试环境中使用的静态文件（比如JS，CSS）都跟线上一样是来自CDN的，<br />
修改后在CDN中同步要等10几分钟，在页面里生效又要等几分钟<br />
每次做了修改，就算是简单的bugfix，也要经历很多环节才能发布上线<br />
（点）这是土豆网首页HTML底部的截图<br />
可以看到上面的红圈是系统自动生成的静态文件版本号，用来控制浏览器缓存<br />
下面这行注释后面的代码是从UI文件服务器上自动抓取嵌入到页面里的<br />
这个首页本身也是静态化的</p>
<p>11<br />
这些流程也带来一些问题(点)<br />
我一直很反对的是，在改进过程的时候损害开发者的利益<br />
如果过程改进增加了开发成本，不应该觉得是理所当然的<br />
而是说明有某些地方没做好，或者缺少了某些东西，比如工具<br />
好的过程应该能隐藏复杂性，减少出错机会。<br />
同时这些环节也对代码的管理提出更高要求，<br />
比如有些代码需要独立的测试，每次修改也要缩小影响范围，<br />
很多东西都依赖代码单元和文件的粒度。</p>
<p>12<br />
第三个现状<br />
这个应该不用解释，上周我刚参加过北京的velocity性能大会<br />
可以看到现在大家对前端性能都是很重视的。</p>
<p>13<br />
这里存在的问题是跟上一条相关的，<br />
比如最简单的例子，为了方便代码的调试维护，我们会希望把JS文件拆分的很细<br />
比如一个UI插件，希望它是独立的文件。<br />
但是性能优化又要求减少页面里的文件请求数<br />
为了尽可能利用浏览器缓存，可能还需要多个页面共享同一个大文件<br />
这两方面的希望是互相矛盾的</p>
<p>14<br />
刚才回顾了三个方面<br />
他们都对同一个问题提出了要求<br />
（点）就是JS代码本身的组织管理和使用</p>
<p>15<br />
解决的途径之一，就是标题里提到的两个东西</p>
<p>16<br />
这个标题可以拆成三部分<br />
后两个是手段，第一个是背景，先来看一下这个背景</p>
<p>17<br />
在这里我把CommonJS翻译成通用JS，接下来就可以看到为什么要叫通用</p>
<p>18<br />
CommonJS是目前广泛流行的一套API规格<br />
不叫它标准是因为它并不是来自像W3C,ECMA这样的官方组织<br />
而是业界自发组织起来，发展出的项目，而且也正在在逐步成为一个事实标准<br />
事实标准这个词是来自拉丁文的修辞，<br />
意思是法律没有规定，但是“在事实上”或者“执行上”是怎样做<br />
（点）它的反义词则是指有明确的法律，但是人门在现实中不会遵守<br />
说到这两个词我们可以很容易的联想到HTML5和XHTML2，一个典型例子<br />
这个民间项目关注的是更广义的JS开发，不止是浏览器<br />
它的目标是建设一个JS的生态系统</p>
<p>19<br />
有人可能会说现在的JS难道没有生态系统么<br />
但是既然业界有这个目标，就说明即使有生态系统，也存在一些问题<br />
当然其中一个问题是JS缺少服务器端开发需要的API，不过这个不是今天的重点<br />
（点）python,ruby跟JS一样是动态语言，也非常流行，他们有内置的标准库<br />
特别是python，有一个著名的宣传口号是“内置电池”，因为标准库非常全面<br />
除了标准库，他们还有一个更庞大的由社区建立的代码库，其中CPAN是最早最有名的<br />
很多人就是因为这个CPAN的存在，才会选择这个语言或者无法摆脱这个语言<br />
JS我们知道也有大量的开源代码，但对你来说并不是每个代码都能用<br />
比如有的是JQUERY插件，有的是YUI插件<br />
还有一些独立的库即使很小，也必须包含重复的功能，因为它不能依赖其他东西<br />
另外那些在浏览器里运行的代码拿到服务器端当然就更没法用了</p>
<p>20<br />
比如这个例子，是我用Python写的翻墙工具，代码的第一行就是在导入标准库<br />
包括操作系统相关，文件读写，正则表达式<br />
下面几行我又使用了几个第三方代码库，其中的mako是一个HTML模板引擎<br />
要获取这个库，我只需要使用Python的包管理工具<br />
一个命令就能查找、下载、安装它自身和它依赖的其他库，而且都是最新版本<br />
这些东西对开发带来了很大的便利，大幅提高开发效率。</p>
<p>21<br />
回到CommonJS, 最早是在09年初，这个叫kevin的人建立了讨论组，最早其实是叫ServerJS讨论组<br />
他当时写了一篇文章叫《服务器端JS需要什么》，所以最初的推动力是来自服务器端开发的需求<br />
因为如果只局限在浏览器的特殊文化里，不接触其他语言，很多问题和需求可能都察觉不到<br />
这个人是Mozilla的开发者工具团队的工程师，这个团队的创建和它发起的项目都很有名的<br />
比如skywriter可能有人听说过，是一个用JS开发的在线版本编辑器<br />
他好像是turbogears项目的创始人，turbogears是一个python的web开发框架<br />
国外著名的开源项目网站sourceforge的新版就是用它开发的</p>
<p>22<br />
Commonjs本身不提供任何具体实现，它只是约定一套东西，由兼容它的项目去实现，<br />
按照这种约定开发出来的JS应用和模块，不做修改就可以在这些兼容COMMONJS的平台上运行<br />
而我们最需要关注的是它对于模块的约定，后面会介绍具体的代码怎么写</p>
<p>23<br />
接下来看一下广义的通用JS<br />
其实我是借用这个词来概括当前的趋势和背景<br />
它包含两层意思，一方面是在更多领域更多环境里需要使用JS，就是说JS本身通用了<br />
另一方面，JS代码也需要变得通用。</p>
<p>24<br />
我们来看几个例子</p>
<p>25<br />
首先最自然的延伸，浏览器扩展<br />
firefox是最早用JS开发扩展的浏览器，因为实际上它浏览器本身的界面也大量使用JS<br />
但是以前的firefox扩展开发门槛还是很高的，比如要学习XUL，要使用C++的API<br />
现在新的jetpack SDK不但提供了高层的JS API和测试工具，打包工具<br />
还提供了兼容CommonJS的模块机制，让扩展开发轻松了很多</p>
<p>26<br />
比如这是我以前用jetpack SDK的早期版本开发的工具软件，可以算一种自动化测试工具<br />
简单概括就是一个爬虫，提供一个网址入口，它可以顺着超链接一路爬下去<br />
找出所有相连的网页，并且对每一个网页应用你自定义的脚本，最后输出脚本结果的报表<br />
因为这个不是主题而且有时间关系就不演示了<br />
来看看它的代码，其中有一部分界面相关的JS还是以前firefox扩展的写法<br />
不用解释就能看出代码很丑陋吧<br />
这个是新的写法，比刚才清晰多了，可以看到我导入了几个API，每个API都是一个模块<br />
request模块就是AJAX，pageworker相当于iframe，还导入了我自己的库TUI</p>
<p>27<br />
除了firefox，其他浏览器也都开始支持用JS开发扩展，目前最火的当然是google的chrome<br />
我这里给出一个safari扩展的例子，因为还没时间移植到chrome上<br />
这个扩展完全用JS,HTML5和CSS3开发，只用到一张图片，UI和动画效果都是CSS3实现的<br />
开发的时候非常方便，不过也有不爽的地方<br />
就是它的JS没有模块化设计，apple提供的API很少，还做了很多麻烦的限制<br />
其实我一直觉得chrome的扩展开发虽然比firefox简单，但是很难开发很强大很给力的应用</p>
<p>28<br />
再来跳出浏览器，看看移动平台上的例子<br />
(点)比如nokia目前基于厚望的QT Quick，QT本来是一个C++的GUI库<br />
因为这一点有很多不喜欢C++的人不愿意用它，为了讨好开发者<br />
QT quick包含QML，可以用JS和类似JS的声明式语言来快速开发手机或平板电脑上的应用</p>
<p>29<br />
当然更有名的是webOS，应该多数人都听说过了<br />
这个移动操作系统一开始就要求所有软件都用JS开发<br />
新的2.0系统更进一步集成了nodejs，后面会做介绍，它也是CommonJS的兼容实现<br />
也就是说我刚才给firefox扩展开发的JS模块可以直接拿到这里使用</p>
<p>30<br />
除了新的移动平台，电脑桌面上其实也有很多GUI库使用了JS<br />
这里举一个比较新的国产的例子，是豆瓣的洪强宁开发的<br />
这里的ONERING是指魔戒里的一枚戒指统御众戒<br />
所以这个名字意思应该是说同一种JS技术可以开发多种界面<br />
不但能开发web上的，也可以开发桌面上的<br />
我给他提过一个建议, 最好能兼容COMMONJS</p>
<p>31<br />
下一个例子是今年欧洲JS大会上一个演示，这个演示的幻灯片里包含几个饼图<br />
黄色是客户端，蓝色是服务器，紫色是嵌入式<br />
可以看到09年第一届JS大会上的分享100%是关于客户端开发的<br />
到了下一届有1/5是关于JS在服务器的应用，再一下届变成一半比例<br />
到了这一届甚至出现了嵌入式开发，作者希望到下一届能各占1/3</p>
<p>32<br />
实际上这10%的嵌入式内容是指作者自己的分享<br />
他们希望能用JS控制一种在国外非常流行的开源硬件平台</p>
<p>33<br />
这个视频演示了他们使用nodejs开发server，<br />
然后在ipad上通过web界面里的JS代码遥控硬件设备<br />
因为时间关系不在这里播放了……</p>
<p>34<br />
最后的例子当然是服务器端的JS了<br />
目前的绝对主流就是nodejs<br />
传统的服务器端JS都会让人觉得很不靠谱，跟ASP之类的东西差不多。<br />
nodejs的靠谱之处在于它的出发点不是为了在服务器和浏览器用同一种语言做开发<br />
这种需求只是一种个人喜好，不一定是最好的选择，也不一定有实用价值。<br />
nodejs想要推广的是基于事件的异步编程<br />
这种编程模式对我们前端开发者来说好像是天经地义的<br />
因为我们已经习惯了浏览器里的各种DOM事件和匿名的回调函数，<br />
AJAX请求，图片加载，也都是异步的<br />
但是对服务器上的开发者来说这是一种需要额外支持，需要努力去适应的模式<br />
JS天生就提供这种支持，而这种编程模式的好处<br />
就是可以适应大规模并发和实时性非常高的服务器应用<br />
比如像webQQ这样的东西。<br />
第三条里提到的erlang (erlan) 是以并发性能著称的函数式编程语言<br />
Nodejs被拿来跟它比较，就算比不过，也说明Nodejs性能有竞争力</p>
<p>35<br />
具体的例子因为时间关系就算了，重点是想强调一下它的模块数量<br />
/*<br />
这里如果是乔布斯演讲，幻灯片上应该会掉下一个很大的550<br />
*/<br />
github的一个wiki页面上收录了很多Nodejs的第三方模块<br />
我随便抓取了一下数量，有550个以上，涉及各种功能。<br />
对于一个发布刚好一年的项目来说这应该算蛮惊人的。</p>
<p>36<br />
回头来看浏览器上的JS，跟刚才的一对比就会感觉通用的模块太少<br />
这里说的通用还仅仅只是在前端，在不同项目不同团队不同公司之间通用<br />
前端的JS社区很分散，jquery有jquery的社区，YUI有YUI的<br />
虽然有一些互相借鉴但是还是有很多东西只在内部传播和使用<br />
外部的开发者是不了解的，也不会去用<br />
而且缺少有利于分享的基础设施，这里说的基础设施不是指开源网站<br />
当然那个也算，这里要说的是更底层的设施</p>
<p>37<br />
其中之一就是模块机制，也就是这次分享的第三个部分</p>
<p>38<br />
先放大视野，看一下其他语言里的模块是什么样子<br />
（点）先请出刚才提到过的python, python代码很简洁，相信没用过的人也看的懂<br />
（点）这里一个框表示一个代码文件<br />
这个文件导入了模块B，然后调用模块B里的say方法<br />
模块B的用法就像这个文件里的一个普通对象一样<br />
（点）模块B定义了两个变量和刚才调用过的say函数<br />
而这个函数里又调用了一个叫cat的类，生成猫的实例，让它叫一下<br />
但是模块B文件里并没有cat类的定义，看第一行可以知道这个类是从模块A里导入进来的<br />
（点）模块A文件里也定义了a变量，但是因为没有声明导入它，<br />
所以不会覆盖模块B文件里定义的a<br />
这个就是python里模块的基本用法<br />
从中我们可以总结几条python模块的特性</p>
<p>39<br />
可以发现这些特性都符合开发者的直觉，也符合开发的需要，<br />
对模块的开发和使用都很有好处<br />
这里没时间演示其他语言的模块，比如ruby, actionscript3，但是这些特性都差不多的<br />
看了这个列表, 我们还可以发现另一件事情<br />
（点）浏览器里的JS不符合其中任何一条</p>
<p>40<br />
可以对比一下：<br />
JS存在全局作用域，不同文件会共享同一个全局命名空间（点）<br />
所有文件一开始都会解析执行（点）<br />
没有相关的声明语句，只能用异步加载文件的方式模拟导入的效果（点）<br />
导入之后不管你想不想要，那个文件里的东西会全部注入到当前的命名空间里（点）<br />
可能隐式的导入很多全局变量，覆盖或修改当前的内容（点）</p>
<p>为了避免这种情况，模块文件就不能采用最自然最简单的写法，比如直接定义变量和函数<br />
而必须把所有东西都放到一个特殊的命名空间下面，比如jquery.js就是这样</p>
<p>JS文件自身也不包含依赖信息，如果有打包合并之类的操作<br />
我们可能会把依赖信息写在另外的配置文件里（点）</p>
<p>41<br />
我们来看看JS的代码通常是怎样组织的<br />
（点）这个是最传统的写法，现在仍然有人在用<br />
（点）某个网站的HTML截图，文件的顺序就是代码的依赖关系<br />
（点）这个已经算是比较新的方法，用工具自动合并这些文件<br />
但是如果这张图里的文件还是刚才那些文件，本质上是没有区别的，仍然依赖从上到下的顺序</p>
<p>42<br />
因为这些传统，我们对浏览器端的特殊文化已经习以为常，见怪不怪了<br />
可能没有觉得有什么不对，但是时间长了会觉得很麻烦和低效<br />
不过最后这一条起到了一定的正面推动作用<br />
为了改善前端性能，很多开发者开始尝试封装出一些工具</p>
<p>43<br />
我把它们称作脚本加载器</p>
<p>44<br />
比如这个例子，它的API提供了串行和并行加载脚本文件的功能<br />
最大的特点应该算是用类似jquery的链式调用风格来实现串行加载<br />
（点）（点）</p>
<p>45<br />
这是另一个库，API风格有很大不同，我们看看有没有新功能<br />
（点）（点）所以这里的并行下载，按依赖关系执行，<br />
只是用预加载技术模拟出来的效果，实际上会请求多次<br />
而且依赖关系仍然取决于前后顺序（点）（点）（点）<br />
本质上还上一个库是一样的</p>
<p>46<br />
最后一个例子是土豆自己的（点）(点）<br />
JS文件名里包含在版本号是在HTML里自动生成的<br />
（点）（点）<br />
(点）虽然当时命名成module，本质上还是脚本加载器</p>
<p>47<br />
除了大同小异的脚本加载器，我们还习惯了另一种代码组织方式<br />
（点）这种模块模式同样也是为了克服之前列举的JS的缺陷</p>
<p>刚才列举的这些东西虽然有帮助，但是跟其他语言原生的模块支持相比，仍然差距很大</p>
<p>48<br />
于是有人提出了更本质上的问题：JavaScript需要模块！<br />
（点）这个名字叫戴夫赫尔曼的人并不是随便说说而已<br />
（点）他的条件很好，跟JS创始人在一起工作，而且是TC39的成员，<br />
TC39是负责制定下一代JS标准的小组<br />
所以他直接发起了一个新提案，希望给JS语言加入simple module的功能</p>
<p>49<br />
第二个链接是他在TC39会议上做的演讲，描述了simple module的目标和初步设计<br />
下面这个N开头的东西是mozilla开发的实验性JS引擎，可以快速加入新功能做测试</p>
<p>50<br />
简单来说他设想的simple module就是这个样子<br />
增加了四个重要的声明语法，虽然语法很简单，但是有了这四个词之后，<br />
JS就完全具备了跟python模块一样强大的功能</p>
<p>51<br />
刚才的代码没看的明白也没关系，因为第一，它目前还只是一个稻草人提案，<br />
就是说这个提案的功能是吸引更多人来讨论它的缺点，从而产生新的和更好的方案<br />
第二，它是一种新引入的语法，跟CommonJS不一样，CommonJS是要用现有的语法去改善JS开发<br />
而simple module的初衷是直接改善JS语言本身，<br />
ES5的邮件列表里有一个相关的讨论，JS创始人布兰登也发表了意见</p>
<p>52<br />
虽然短时间内不能用，但是可以先借鉴一下这个提案里列举的目标<br />
我们是否能利用现有的JS语法和功能，来追求这些目标，实现比较理想的模块机制呢</p>
<p>53<br />
之前好几次提到CommonJS的模块，现在终于轮到讨论它了</p>
<p>54<br />
先请出之前展示过的爬虫程序，在介绍firefox扩展的时候，提到过它实现了CommonJS的模块<br />
这里给出的两段代码分别来自同一个模块文件的顶部和底部（点）<br />
圈出的部分就是CommonJS模块的主要特征（点）</p>
<p>55<br />
（点）把之前python模块的示例代码，直接改成commonjs的写法（点）（点）功能特性完全一致<br />
区别只是导入模块时不是用声明语句，而是调用require函数<br />
可以说CommonJS满足了之前提出的所有要求，<br />
在不引入新语法的前提下，实现了比较理想的模块机制<br />
可惜这种代码完全没办法在浏览器里使用，障碍有两个：<br />
第一，网页里不同JS文件之间全局命名空间是共享，而服务器端CommonJS里每个文件都是独立的<br />
第二，require函数是阻塞式的，读取完模块文件，并返回模块对象之前，不会执行后续的代码<br />
在服务器上这是很自然的，但是在浏览器里，读取文件是异步操作，阻塞会影响页面的交互<br />
所以没办法、也不能让require函数阻塞代码的执行</p>
<p>56<br />
于是现在要解决的问题转变成了这个了<br />
不过在讲解决方案之前，我要先插播两页</p>
<p>57</p>
<p>58</p>
<p>59<br />
嗯接下来开始介绍浏览器里的CommonJS兼容实现：RequireJS<br />
它的开发者比我条件好，近水楼台先得月……<br />
它定义了两个方法，require和define，其中define是关键设计，<br />
已经成为了新的CommonJS规范，叫做异步模块</p>
<p>60<br />
来看看所谓异步模块是什么样的<br />
（点）还是跟之前Python模块和CommonJS模块的示例代码保持一致（点）（点）<br />
可以看到require变成异步调用，第二个参数是匿名函数，<br />
这个函数的作用域相当于模块文件的顶层作用域<br />
作用域里的代码可以跟服务器端CommonJS完全一致，<br />
包括使用阻塞式的require，用exports生成模块对象<br />
这个作用域里也可以直接采用传统的模块模式的写法，用return来生成模块对象<br />
依赖的模块会被转变成模块对象，通过函数参数传入<br />
define函数具备require的所有功能，同时提供了定义新模块的能力，<br />
当模块代码位于独立的文件里<br />
比如像这里的模块A，模块名称的参数可以省略，直接绑定到文件名</p>
<p>61<br />
异步模块的require和define还有一种衍生的用法，就是用来请求JSONP接口<br />
define不但支持传入函数，也可以直接传入一个对象作为模块对象<br />
用这个方法请求JSONP的好处是不用担心callback污染全局命名空间，<br />
还可以起到缓存的效果，因为模块文件只会加载一次</p>
<p>62<br />
总结一下异步模块的优点</p>
<p>63<br />
刚才说过requireJS算是异步模块的一个官方实现，<br />
不过相比之下我更喜欢自己实现的oz.js<br />
一个原因是代码更少更简单，另一个原因是我对define函数的用法有不同的意见<br />
requirejs仍然采用服务器端的做法，把模块名直接等同于文件地址，<br />
但是前端开发中很少有这么理想的情况<br />
而对于要下载的JS文件不需要做静态的声明，只在运行时里检查，也会产生很多不便</p>
<p>64<br />
对照代码看看oz.js的def方法有什么不同</p>
<p>65<br />
内部细节只强调几个功能上的问题<br />
oz.js本身包含了前面提到的脚本加载器的所有功能，但是只会用到并行加载，<br />
因为模块文件之间没有依赖关系。</p>
<p>66<br />
在模块部分的最后引用一下这句话：“让代码更容易分享，大家就会分享更多的代码”。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2010/12/19/module-and-compiler-for-common-js/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Google的大危机——本地app重新流行！浏览器和web已死？</title>
		<link>http://www.limboy.com/2010/08/21/app-vs-web/</link>
		<comments>http://www.limboy.com/2010/08/21/app-vs-web/#comments</comments>
		<pubDate>Sat, 21 Aug 2010 14:02:58 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[web服务/应用]]></category>
		<category><![CDATA[科技]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=336</guid>
		<description><![CDATA[这个星期连线杂志的文章《浏览器已死，互联网永生》（中文）成功的引发话题，即使在中国都引发了广泛激烈的争论，以下这段评论我本来是像往常一样用google reader的note来写的，但是不小心写长了-__-b，干脆发到这里，文字没时间修改所以也没有笑点，我只是觉得这些很明显的道理，在很多人的文章里没看到提起，所以如梗在喉……
引发连线思考的，并非一份统计数据，而是本地应用（native app）重新流行的现象，连线把这种现象解读为：商业战胜乌托邦、垄断战胜混乱、封闭战胜开放、便利战胜多样、营销战胜传播、性能战胜创新、稀少战胜丰富、内容战胜技术……显然YY过头了，这些观点随便抽出一个都不可能不引发争议。而实际上呢，这个现象背后真正分出胜负的对战双方，应该是移动设备战胜传统电脑。
先想想web的优势：跨平台、即需即用、一致性、安装和升级的成本为0、托管数据、托管计算任务、自由开放、实现和分发新产品新内容的成本低门槛低——最后两条导致新产品新内容层出不穷。
在桌面电脑上，这些都是绝对无敌的杀手级特性，本地软件即便在用户体验和性能方面有优势，在web的巨大优势面前也是杯水车薪。所以我们看到：即使在第三方软件用户体验最高（平均…）的OS X平台上，本地软件替代web的情况都极少，相反，因为google reader，像NetNewsWire这样的阅读器软件销声匿迹。因为gmail，困扰开源社区多年的outlook终于有了替代品。我们也并没有下载安装一大堆本地app专门用来访问连线、NYT、维基、google maps、facebook&#8230;&#8230;只有在那些web还没发展出成熟技术的领域，本地app才会无法取代，比如代码编辑器（vim/eclipse）和音乐管理（itunes）。也许有人认为twitter是一个app取代浏览器的例子……请问，早期的twitter真的是一个website或者webapp么？实际上只是一个数据服务罢？
正因如此，就在不久前，人们还经常畅谈web和浏览器取代操作系统，google也毫不动摇的坚守在浏览器里。为什么现在突然变调，开始有人怀疑浏览器将死了？
是因为移动设备火了。开头列举的web优势，并不全都适用于移动设备——我指的是“跨平台、即需即用、一致性”，人们经常需要使用不同的电脑：住宅里的台式机、公司里的工作站、咖啡馆里的笔记本……但是移动设备，比如手机和ipad，却几乎肯定是一人一机，没有切换的可能性，于是“即需即用”变成了“事先装好以后常用”、跨平台和一致性的需求也没了。另一方面由于app store的出现，移动平台上软件的安装和升级成本也大幅降低了（虽然对像我这样装了200+软件的用户来说升级还是很麻烦）。而“托管数据”和“托管计算任务”，也不再是浏览器的专利，在随时与网络连接、自身资源有限的移动设备上，本地app也大量使用云端的托管。因为这些原因，web/浏览器的优势被抵消了大半，本地app在用户体验和性能方面的优势凸显出来，成了最佳选择……
但是别忘了，web的优势还剩下两条：“自由开放、实现和分发新产品新内容的成本低门槛低“。仅凭这两条，web就拥有独一无二的生命力，也永远不会被app取代。想想看：世界上真正有几家企业的软件或内容服务，能为广大用户熟知，能轻易的说服广大用户下载安装甚至购买？假如没有浏览器里的web，这个世界就只有大厂商和传统媒体能生存，只会有封闭的、不一致的平台。新事物、新内容、新企业的出现都会变的很难、很慢、很少。一个成员数量接近七十亿的人类社会能接受这种世界么？
一种产品或内容，不论多么优秀多么创新的，都不会一直是最好，因为永远会出现更好。一种现状，无论多么尽善尽美，都不可能抑制住一些人对创造和自我实现的向往。一个企业，无论多么强大，也不可能满足长尾上的每一点需求、不可能看到每一个能通向引爆点的新方向。一个平台，即使是apple出品，即使它值得学习值得崇拜，但是值得去局限自己的视野、封闭自己的思维么——我觉得《连线》的编辑就是这样做的。
另外，就算是移动设备，也不适合所有人都一窝蜂推出本地app，上上周在书店遇到都市客的技术总监小叶同志，我也对他们的周末画报app泼过类似的凉水，小叶同志说重要的是”先圈地“，我认为……地是很有限的。比方说，我喜欢google reader的web界面，更喜欢ipad上的本地客户端Reeder，但要是你以为你的产品也能复制这种成功，用本地app来取代web界面，那就大错特错了——除非你是真正的杀手级应用，或者极少数垄断性内容媒体，否则除了死geek，没人会把你的app，连同另外上百个类似的app都安装保留在移动设备上面，我们只可能在web上，通过链接的跳转，偶尔访问到你。如果没有web，没有浏览器，你早就死了。

]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.limboy.com/wp-content/uploads/2010/08/apple-app-store.jpg"><img src="http://www.limboy.com/wp-content/uploads/2010/08/apple-app-store-300x174.jpg" alt="" title="apple-app-store" width="300" height="174" style="float:left;margin:0 10px 0 0;" /></a>这个星期连线杂志的文章<a href="http://www.wired.com/magazine/2010/08/ff_webrip/all/1" target="_blank">《浏览器已死，互联网永生》</a>（<a href="http://tech.sina.com.cn/i/2010-08-18/19554560539.shtml" target="_blank">中文</a>）成功的引发话题，即使在中国都引发了广泛激烈的争论，以下这段评论我本来是像<a href="http://www.google.com/profiles/dexter.yy" target="_blank">往常</a>一样用google reader的note来写的，但是不小心写长了-__-b，干脆发到这里，文字没时间修改所以也没有笑点，我只是觉得这些很明显的道理，在很多人的文章里没看到提起，所以如梗在喉……</p>
<p>引发连线思考的，并非一份<a href="http://www.techcrunchchina.com/2940" target="_blank">统计数据</a>，而是本地应用（native app）重新流行的现象，连线把这种现象解读为：商业战胜乌托邦、垄断战胜混乱、封闭战胜开放、便利战胜多样、营销战胜传播、性能战胜创新、稀少战胜丰富、内容战胜技术……显然YY过头了，这些观点随便抽出一个都不可能不引发争议。而实际上呢，这个现象背后真正分出胜负的对战双方，应该是移动设备战胜传统电脑。<span id="more-336"></span></p>
<p>先想想web的优势：跨平台、即需即用、一致性、安装和升级的成本为0、托管数据、托管计算任务、自由开放、实现和分发新产品新内容的成本低门槛低——最后两条导致新产品新内容层出不穷。</p>
<p>在桌面电脑上，这些都是绝对无敌的杀手级特性，本地软件即便在用户体验和性能方面有优势，在web的巨大优势面前也是杯水车薪。所以我们看到：即使在第三方软件用户体验最高（平均…）的OS X平台上，本地软件替代web的情况都极少，相反，因为google reader，像NetNewsWire这样的阅读器软件销声匿迹。因为gmail，困扰开源社区多年的outlook终于有了替代品。我们也并没有下载安装一大堆本地app专门用来访问连线、NYT、维基、google maps、facebook&#8230;&#8230;只有在那些web还没发展出成熟技术的领域，本地app才会无法取代，比如代码编辑器（vim/eclipse）和音乐管理（itunes）。也许有人认为twitter是一个app取代浏览器的例子……请问，早期的twitter真的是一个website或者webapp么？实际上只是一个数据服务罢？</p>
<p>正因如此，就在不久前，人们还经常畅谈web和浏览器取代操作系统，google也毫不动摇的坚守在浏览器里。为什么现在突然变调，开始有人怀疑浏览器将死了？</p>
<p>是因为移动设备火了。开头列举的web优势，并不全都适用于移动设备——我指的是“跨平台、即需即用、一致性”，人们经常需要使用不同的电脑：住宅里的台式机、公司里的工作站、咖啡馆里的笔记本……但是移动设备，比如手机和ipad，却几乎肯定是一人一机，没有切换的可能性，于是“即需即用”变成了“事先装好以后常用”、跨平台和一致性的需求也没了。另一方面由于app store的出现，移动平台上软件的安装和升级成本也大幅降低了（虽然对像我这样装了200+软件的用户来说升级还是很麻烦）。而“托管数据”和“托管计算任务”，也不再是浏览器的专利，在随时与网络连接、自身资源有限的移动设备上，本地app也大量使用云端的托管。因为这些原因，web/浏览器的优势被抵消了大半，本地app在用户体验和性能方面的优势凸显出来，成了最佳选择……</p>
<p>但是别忘了，web的优势还剩下两条：“自由开放、实现和分发新产品新内容的成本低门槛低“。仅凭这两条，web就拥有独一无二的生命力，也永远不会被app取代。想想看：世界上真正有几家企业的软件或内容服务，能为广大用户熟知，能轻易的说服广大用户下载安装甚至购买？假如没有浏览器里的web，这个世界就只有大厂商和传统媒体能生存，只会有封闭的、不一致的平台。新事物、新内容、新企业的出现都会变的很难、很慢、很少。一个成员数量接近七十亿的人类社会能接受这种世界么？</p>
<p>一种产品或内容，不论多么优秀多么创新的，都不会一直是最好，因为永远会出现更好。一种现状，无论多么尽善尽美，都不可能抑制住一些人对创造和自我实现的向往。一个企业，无论多么强大，也不可能满足长尾上的每一点需求、不可能看到每一个能通向引爆点的新方向。一个平台，即使是apple出品，即使它值得学习值得崇拜，但是值得去局限自己的视野、封闭自己的思维么——我觉得《连线》的编辑就是这样做的。</p>
<p>另外，就算是移动设备，也不适合所有人都一窝蜂推出本地app，上上周在书店遇到都市客的技术总监小叶同志，我也对他们的周末画报app泼过类似的凉水，小叶同志说重要的是”先圈地“，我认为……地是很有限的。比方说，我喜欢google reader的web界面，更喜欢ipad上的本地客户端<a href="http://reederapp.com/ipad/" target="_blank">Reeder</a>，但要是你以为你的产品也能复制这种成功，用本地app来取代web界面，那就大错特错了——除非你是真正的杀手级应用，或者极少数垄断性内容媒体，否则除了死geek，没人会把你的app，连同另外上百个类似的app都安装保留在移动设备上面，我们只可能在web上，通过链接的跳转，偶尔访问到你。如果没有web，没有浏览器，你早就死了。</p>
<p><img src="http://www.limboy.com/wp-content/uploads/2010/08/dead-300x203.jpg" alt="" title="dead" width="300" height="203" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2010/08/21/app-vs-web/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Google I/O大会keynote摘要</title>
		<link>http://www.limboy.com/2010/05/20/google-io-summary/</link>
		<comments>http://www.limboy.com/2010/05/20/google-io-summary/#comments</comments>
		<pubDate>Wed, 19 May 2010 19:10:19 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[OpenSource]]></category>
		<category><![CDATA[web服务/应用]]></category>

		<guid isPermaLink="false">http://www.limboy.com/?p=274</guid>
		<description><![CDATA[


VP8开源，免专利费，发布新的web视频格式 WebM

WebM的组成包括：VP8（视频编码） + Vorbis（音频编码） + Matroska（即mkv，容器格式） ，文件后缀.webm
VP8的FAQ：http://www.webmproject.org/about/faq/
来自x264开发者的VP8深度技术分析：http://x264dev.multimedia.cx/?p=377


 


几乎所有浏览器厂商都宣布支持VP8：

Chromium：http://build.chromium.org/buildbot/snapshots 
Chrome在24号更新 
Firefox：http://nightly.mozilla.org/webm/ 
Opera：http://labs.opera.com/news/2010/05/19/ 
微软宣布IE9将支持VP8：http://windowsteamblog.com/windows/b/bloggingwindows/archive/2010/05/19/another-follow-up-on-html5-video-in-ie9.aspx 
Adobe在会上宣布flash支持webm/VP8，这样flash将支持5种codec：Screen sharing, Spark, VP6, H.264, VP8 


 

Adobe发布HTML5开发工具

dreamweaver的HTML5 Pack：http://labs.adobe.com/technologies/html5pack/
同时测试多种浏览器设备（Multiscreen Preview panel）
支持编辑和渲染CSS3，包括动画，有一个demo看上去很像用flash开发广告banner


  

Chrome Web Store

帮助用户寻找web app，可以在Chrome app tab上创建软件的快捷方式：http://code.google.com/chrome/apps/
内建支付系统，支持付费软件
包含flash软件
包含Native Client应用（原生程序＋HTML5 API），3D游戏可以全屏运行
包含出版物，演示了HTML5 magazine


  

Google Wave正式开放，包含一堆API和扩展机制，跟gmail整合

  

API更新

Font API：http://code.google.com/apis/webfonts/
Feed API支持PubSubHubbub：http://googleajaxsearchapi.blogspot.com/2010/05/google-feed-api-now-with-instant.html
Maps API v3从labs里毕业


  

Google Web Toolkit 和 Google Ap Engine

跟VMware合作，整合 GWT 和 Spring（SpringSource Tool Suite， [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.limboy.com/2010/05/20/google-io-summary/"><img src="http://code.google.com/events/images/io2010logo.png" alt="" style="margin:0 10px 10px 0;float:left;width:240px" /></a>
<ol>
<li>
<h3>VP8开源，免专利费，发布新的web视频格式 WebM</h3>
<ul>
<li>WebM的组成包括：VP8（视频编码） + Vorbis（音频编码） + Matroska（即mkv，容器格式） ，文件后缀.webm</li>
<li>VP8的FAQ：<a href="http://www.webmproject.org/about/faq/">http://www.webmproject.org/about/faq/</a></li>
<li>来自x264开发者的VP8深度技术分析：<a href="http://x264dev.multimedia.cx/?p=377">http://x264dev.multimedia.cx/?p=377</a></li>
</ul>
</li>
<p> <br/><br />
<span id="more-274"></span></p>
<li>
<h3>几乎所有浏览器厂商都宣布支持VP8：</h3>
<ul>
<li>Chromium：<a href="http://build.chromium.org/buildbot/snapshots">http://build.chromium.org/buildbot/snapshots</a> </li>
<li>Chrome在24号更新 </li>
<li>Firefox：<a href="http://nightly.mozilla.org/webm/">http://nightly.mozilla.org/webm/</a> </li>
<li>Opera：<a href="http://labs.opera.com/news/2010/05/19/">http://labs.opera.com/news/2010/05/19/</a> </li>
<li>微软宣布IE9将支持VP8：<a href="http://windowsteamblog.com/windows/b/bloggingwindows/archive/2010/05/19/another-follow-up-on-html5-video-in-ie9.aspx">http://windowsteamblog.com/windows/b/bloggingwindows/archive/2010/05/19/another-follow-up-on-html5-video-in-ie9.aspx</a> </li>
<li>Adobe在会上宣布flash支持webm/VP8，这样flash将支持5种codec：Screen sharing, Spark, VP6, H.264, VP8 </li>
</ul>
</li>
<p> <br/></p>
<li>
<h3>Adobe发布HTML5开发工具</h3>
<ul>
<li>dreamweaver的HTML5 Pack：<a href="http://labs.adobe.com/technologies/html5pack/">http://labs.adobe.com/technologies/html5pack/</a></li>
<li>同时测试多种浏览器设备（Multiscreen Preview panel）</li>
<li>支持编辑和渲染CSS3，包括动画，有一个demo看上去很像用flash开发广告banner</li>
</ul>
</li>
<p>  <br/></p>
<li>
<h3>Chrome Web Store</h3>
<ul>
<li>帮助用户寻找web app，可以在Chrome app tab上创建软件的快捷方式：<a href="http://code.google.com/chrome/apps/">http://code.google.com/chrome/apps/</a></li>
<li>内建支付系统，支持付费软件</li>
<li>包含flash软件</li>
<li>包含Native Client应用（原生程序＋HTML5 API），3D游戏可以全屏运行</li>
<li>包含出版物，演示了HTML5 magazine</li>
</ul>
</li>
<p>  <br/></p>
<li>
<h3>Google Wave正式开放，包含一堆API和扩展机制，跟gmail整合</h3>
</li>
<p>  <br/></p>
<li>
<h3>API更新</h3>
<ul>
<li>Font API：<a href="http://code.google.com/apis/webfonts/">http://code.google.com/apis/webfonts/</a></li>
<li>Feed API支持PubSubHubbub：<a href="http://googleajaxsearchapi.blogspot.com/2010/05/google-feed-api-now-with-instant.html">http://googleajaxsearchapi.blogspot.com/2010/05/google-feed-api-now-with-instant.html</a></li>
<li>Maps API v3从labs里毕业</li>
</ul>
</li>
<p>  <br/></p>
<li>
<h3>Google Web Toolkit 和 Google Ap Engine</h3>
<ul>
<li>跟VMware合作，整合 GWT 和 Spring（SpringSource Tool Suite， Spring Roo）<a href="http://www.springsource.org/node/2595">http://www.springsource.org/node/2595</a></li>
<li>GWT 2.1 Widget Libraries，支持移动设备</li>
<li>Google Ap Engine企业版</li>
</ul>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2010/05/20/google-io-summary/feed/</wfw:commentRss>
		<slash:comments>4</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>以国家之名</title>
		<link>http://www.limboy.com/2010/01/10/in-the-name-of-country/</link>
		<comments>http://www.limboy.com/2010/01/10/in-the-name-of-country/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 15:51:45 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Blogger]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[日漫]]></category>
		<category><![CDATA[纯水]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2010/01/10/in-the-name-of-country/</guid>
		<description><![CDATA[从我的Gmail里翻出的记录：

Mon, Feb 4, 2008 at 5:16 AM

subject: 注册信息
尊敬的用户，您的用户信息注册成功！用户名:dexter_yy
Thu, Feb 14, 2008 at 2:14 AM
subject: ICP备案审核通知（审核拒绝）
尊敬的用户:dexter_yy，很遗憾的通知您，您的ICP备案申请不能通过审核，拒绝原因是：您所备案的网站：请确认网站服务内容一栏填写是否准确.
接入商的核实意见：
(1) 信息不正确 请重新核对准确接入商


Mon, Feb 23, 2009 at 8:36 PM
subject: 关于网站备案用户执行“找回密码”操作后新密码的通知
尊敬的用户：dexter_yy，您于2009-02-23 20:33:34使用了备案用户找回密码功能，您找回的密码是：[马赛克]。请慎重保管注册密码！ 工业和信息化部网站备案系统
Wed, Mar 4, 2009 at 1:54 PM
subject: 关于ICP备案信息不符合备案要求退回修正的通知
尊敬的用户，很遗憾的通知您，您的ICP备案申请(limboy.com)，经[上海市通信管理局2]审核，不符合备案要求，现退回修改，原因请登陆系统查询。
Sat, Dec 12, 2009 at 2:59 PM
subject: 关于网站备案用户执行“找回密码”操作后新密码的通知
尊敬的用户：dexter_yy，您于2009-12-12 14:48:31使用了备案用户找回密码功能，您找回的密码是：XXXXXX。请慎重保管注册密码！ 工业和信息化部网站备案系统
Wed, Jan 6, 2010 at 10:45 AM
subject: 关于ICP备案申请审核通过的通知
尊敬的用户：您的ICP备案申请已通过审核,备案/许可证编号为: 沪ICP备10000943号 ，审核通过日期：2010-01-06。 
撒花～
本来我准备只贴出以上这些邮件内容，然后就结束本文点submit按钮发POST请求……但是这种把思考的工作托付给读者的写法，我还是有些不太放心，我担心这会让人误解我的意图，以为我是在嘲讽帝国衙门的政策法规和办事效率，不，如果这是你的理解，你错了，我是在嘲讽自己。
我的blog被关闭了大概有一两个月，在这段时间里，有很多人来问我，我都没回应，因为实在没什么好说的，没有黑幕，没有冤情，没有河蟹。我有充足的时间（早在一两年前我就知道不备案的后果），我有足够的帮助（盘古有专人为客户的备案提供支持），我有相对宽松的环境（直到现在，工信部仍然不会在处理申请的时候去审查网站的内容，甚至都不在乎网站是否存在，你只要去申请，只要你提供的信息不会对他们的工作流程造成困扰，他们就给你发ICP许可证），但我却把早就应该完成的备案，一直拖延到现在。都是我自己的错。
也许有人会说：你到底是真傻逼还是在装逼，错的首先是政府啊，你的blog被关闭，是因为现在这种荒谬愚蠢的国家政策，是因为统治阶层不懂得也不喜欢互联网的开放精神，是因为伟光正要控制信息，是因为工信部的备案系统太难用，是因为公务员的办事效率太低……总之，你怎么能不抱怨呢，你这不是麻木顺从的劣根性么
我会从土豆网里搜出一个视频来作为回答，不是什么经典大片，而是TV动画，如果不是宅男宅女应该就没看过——《地狱少女》第二部的第15话，标题是“以國家之名的墮落”，在这集故事里，女主角百合子的父亲是一个loser，家境穷困，生活很艰辛，他认为一切不幸的根源都是日本当时的首相大泉太一郎（这个名字应该不用注解罢），把全部时间投入到基层的助选活动中，支持另一个首相候选人，为此还不断借债，把自家的小工厂扔给妻子一人支撑。百合子在故事开始的时候就求助于地狱少女，希望把大泉首相立刻送进地狱，因为在这种家庭环境的影响下，她也认为只要没有大泉，人民生活就会幸福。但是后来，她的母亲劳累过度病倒了，在病床上，母亲说出了朴实的真相：
母亲：“不工作就不能生存……”
百合子：“果然这个国家的政治体制很异常！竟然要让人工作到弄跨身体才能生存！这都是大泉政府的错！”
母亲：“不是这样的……”
百合子：“什么不是啊，大泉首相上台前，我上小学的那个时候，生活不是还很轻松吗？！”
母亲：“更痛苦的时候也遇到过。可那时候一家人一起克服过来了，挥汗如雨的工作”。
百合子：“诶？”
虽然大泉的政策确实对百合子家工厂的衰败负有责任，但是导致境况越来越差的却是自己，不幸的根源是自己。自己的生活和自己的事业，最终还是需要自己的努力工作来改善，百合子的父亲把希望完全寄托在大环境的剧变上，但是大环境却不可能永远满足个人愿望，因为社会永远都由各种少数派和多数派拼凑而成，时代永远都像洪流一样让人身不由己的“前进”，正如比古清十郎说的那样：“时代和人心都有弊病，无论你有再强大的力量，也阻止不了时代的洪流。现今如此，今后亦然”。
最后，即使大环境真的剧变了，就能立刻体验到改善么？说到这里我想到了台湾的“马上就好”，想到了美国的“Change Has Come To [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2010/01/10/in-the-name-of-country/change-1jpg/' rel='attachment wp-att-249' title='change-1.jpg'><img src='http://www.limboy.com/wp-content/uploads/2010/01/change-1.jpg' alt='change-1.jpg' style="margin:0 10px 0 0;float:left;" /></a>从我的Gmail里翻出的记录：</p>
<div style="margin-left:255px;">
<h4>Mon, Feb 4, 2008 at 5:16 AM</h4>
<blockquote><p>
subject: 注册信息</p>
<p>尊敬的用户，您的用户信息注册成功！用户名:dexter_yy</p></blockquote>
<h4>Thu, Feb 14, 2008 at 2:14 AM</h4>
<blockquote><p>subject: ICP备案审核通知（审核拒绝）</p>
<p>尊敬的用户:dexter_yy，很遗憾的通知您，您的ICP备案申请不能通过审核，拒绝原因是：您所备案的网站：请确认网站服务内容一栏填写是否准确.<br />
接入商的核实意见：<br />
(1) 信息不正确 请重新核对准确接入商</p></blockquote>
</div>
<p><span id="more-248"></span></p>
<h4>Mon, Feb 23, 2009 at 8:36 PM</h4>
<blockquote><p>subject: 关于网站备案用户执行“找回密码”操作后新密码的通知</p>
<p>尊敬的用户：dexter_yy，您于2009-02-23 20:33:34使用了备案用户找回密码功能，您找回的密码是：[马赛克]。请慎重保管注册密码！ 工业和信息化部网站备案系统</p></blockquote>
<h4>Wed, Mar 4, 2009 at 1:54 PM</h4>
<blockquote><p>subject: 关于ICP备案信息不符合备案要求退回修正的通知</p>
<p>尊敬的用户，很遗憾的通知您，您的ICP备案申请(limboy.com)，经[上海市通信管理局2]审核，不符合备案要求，现退回修改，原因请登陆系统查询。</p></blockquote>
<h4>Sat, Dec 12, 2009 at 2:59 PM</h4>
<blockquote><p>subject: 关于网站备案用户执行“找回密码”操作后新密码的通知</p>
<p>尊敬的用户：dexter_yy，您于2009-12-12 14:48:31使用了备案用户找回密码功能，您找回的密码是：XXXXXX。请慎重保管注册密码！ 工业和信息化部网站备案系统</p></blockquote>
<h4>Wed, Jan 6, 2010 at 10:45 AM</h4>
<blockquote><p>subject: 关于ICP备案申请审核通过的通知</p>
<p>尊敬的用户：您的ICP备案申请已通过审核,备案/许可证编号为: 沪ICP备10000943号 ，审核通过日期：2010-01-06。 </p></blockquote>
<p>撒花～</p>
<p>本来我准备只贴出以上这些邮件内容，然后就结束本文点submit按钮发POST请求……但是这种把思考的工作托付给读者的写法，我还是有些不太放心，我担心这会让人误解我的意图，以为我是在嘲讽帝国衙门的政策法规和办事效率，不，如果这是你的理解，你错了，我是在嘲讽自己。</p>
<p>我的blog被关闭了大概有一两个月，在这段时间里，有很多人来问我，我都没回应，因为实在没什么好说的，没有黑幕，没有冤情，没有河蟹。我有充足的时间（早在一两年前我就知道不备案的后果），我有足够的帮助（<a href="http://www.paangood.com/index.php" target="_blank">盘古</a>有专人为客户的备案提供支持），我有相对宽松的环境（直到现在，工信部仍然不会在处理申请的时候去审查网站的内容，甚至都不在乎网站是否存在，你只要去申请，只要你提供的信息不会对他们的工作流程造成困扰，他们就给你发ICP许可证），但我却把早就应该完成的备案，一直拖延到现在。都是我自己的错。</p>
<p>也许有人会说：你到底是真傻逼还是在装逼，错的首先是政府啊，你的blog被关闭，是因为现在这种荒谬愚蠢的国家政策，是因为统治阶层不懂得也不喜欢互联网的开放精神，是因为伟光正要控制信息，是因为工信部的<a target="_blank" href="http://www.google.com/search?q=%E5%B7%A5%E4%BF%A1%E9%83%A8%E7%BD%91%E7%AB%99%E5%A4%87%E6%A1%88%E7%B3%BB%E7%BB%9F%E5%A4%AA%E7%83%82%E6%98%AF%E5%A4%A7%E9%87%8F%E7%BD%91%E7%AB%99%E6%B2%A1%E6%9C%89%E5%A4%87%E6%A1%88%E7%9A%84%E4%B8%BB%E8%A6%81%E5%8E%9F%E5%9B%A0">备案系统太难用</a>，是因为公务员的办事效率太低……总之，你怎么能不抱怨呢，你这不是麻木顺从的劣根性么</p>
<p>我会从土豆网里搜出一个视频来作为回答，不是什么经典大片，而是TV动画，如果不是宅男宅女应该就没看过——《地狱少女》第二部的第15话，标题是“以國家之名的墮落”，在这集故事里，女主角百合子的父亲是一个loser，家境穷困，生活很艰辛，他认为一切不幸的根源都是日本当时的首相大泉太一郎（这个名字应该不用注解罢），把全部时间投入到基层的助选活动中，支持另一个首相候选人，为此还不断借债，把自家的小工厂扔给妻子一人支撑。百合子在故事开始的时候就求助于地狱少女，希望把大泉首相立刻送进地狱，因为在这种家庭环境的影响下，她也认为只要没有大泉，人民生活就会幸福。但是后来，她的母亲劳累过度病倒了，在病床上，母亲说出了朴实的真相：</p>
<p>母亲：“不工作就不能生存……”<br />
百合子：“果然这个国家的政治体制很异常！竟然要让人工作到弄跨身体才能生存！这都是大泉政府的错！”<br />
母亲：“不是这样的……”<br />
百合子：“什么不是啊，大泉首相上台前，我上小学的那个时候，生活不是还很轻松吗？！”<br />
母亲：“更痛苦的时候也遇到过。可那时候一家人一起克服过来了，挥汗如雨的工作”。<br />
百合子：“诶？”</p>
<p>虽然大泉的政策确实对百合子家工厂的衰败负有责任，但是导致境况越来越差的却是自己，不幸的根源是自己。自己的生活和自己的事业，最终还是需要自己的努力工作来改善，百合子的父亲把希望完全寄托在大环境的剧变上，但是大环境却不可能永远满足个人愿望，因为社会永远都由各种少数派和多数派拼凑而成，时代永远都像洪流一样让人身不由己的“前进”，正如比古清十郎说的那样：“时代和人心都有弊病，无论你有再强大的力量，也阻止不了时代的洪流。现今如此，今后亦然”。</p>
<p>最后，即使大环境真的剧变了，就能立刻体验到改善么？说到这里我想到了台湾的“马上就好”，想到了美国的“Change Has Come To America”，想到了日本的“政权更迭”……只要自己不行动，改善就不可能从天而降。如果等到那时才行动，就更不可能“马上就好”。既然早晚要行动，为什么不从现在就开始？</p>
<p>以国家之名的懒惰，以国家之名的松懈，以国家之名的放弃，也许能赢得一些同情和理解，但是最终失去那些东西的仍然是我们自己。</p>
<p>最后，百合子委托给地狱少女的不是大泉首相，而是自己的父亲。完整视频：</p>
<p><object width="500" height="380"><param name="movie" value="http://www.tudou.com/v/734oFQo5HwE"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/734oFQo5HwE" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object></p>
<p>PS：其实我并不是因为没及时备案就妄想出这些，而是因为长时间以来在twitter上体验到的氛围，积压在心底。</p>
<p>PS2：我的“拖延”习惯貌似是一种症状，叫“Procrastination”，由于最近帝国对网络的打击，相关文章的链接失效了^_^b&#8230;..请自行搜索……如果不是看了那些文章，我还以为这是个性呢……</p>
<p>PS3：虽然我常常几个月都不更新blog，但是在blog关掉的这段时间里，却叛逆似的积压了好几篇……有的发在论坛，有的放在evernote里，接下来会找时间发出来，希望不要拖延-___-b</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2010/01/10/in-the-name-of-country/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>我爱灾难片！讨论一下《2012》的细节和背景</title>
		<link>http://www.limboy.com/2009/11/14/mayan2012/</link>
		<comments>http://www.limboy.com/2009/11/14/mayan2012/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 00:05:11 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[SF/F]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[电影]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/11/14/mayan2012/</guid>
		<description><![CDATA[《2012》最大的缺点还是世界毁灭的太快了，悬念做的不够，我更喜欢cloverfield那种调调，此外视觉效果还是有点单调，这年头只靠一个卷起肯尼迪航母的海啸背景已经唬不住人了，观众眼里尽是绿幕。不过要求太高也是不厚道的，总体来说，《2012》只要把那些传统的美式英雄主义和小范围人道主义的部分剪掉换成特效就相当完美叻！ 
先说几个细节：
　　
1，好莱坞影片里常见的mac笔记本，这次完全没有看到，VAIO则至少清晰的出现了5次，主角之一的科学家和白宫官员都用sony笔记本，此外加长林肯在主角逃出加州过程中的表现很明显的说明福特也是出过钱的。
　　
2，黄石公园的超级火山喷发让华盛顿特区进入核冬天，我感觉这个不太靠谱，要吸收大部分太阳辐射的能量，浮尘的直径至少要能小于远红外的波长，也就是13微米，核爆可以做到，而火山灰貌似达不到这个程度。
　　
3，通过各国领袖在方舟上进行的表决，我们可以发现：3亿人口的美国独占了一艘船，13亿中国人翰1亿多日本人还有可以忽略的俄国人共用另一艘船，5亿人口的EU占了第三艘船——棒子和阿三明显被抛弃了。而非洲由于陆地上升，反而损失相对较小，重新成为人类发源地，这充分说明出来混迟早要还 XD
　　
4，US军方感叹：选中国没错，只有中国能完成这样的工程。其实中国的优势不光是那些继承能吃苦、能战斗、能奉献的优良传统，一切听党指挥的工人兄弟——登上方舟的船票价格是10亿欧元，按照09年的水平，全球只有790多位大爷买得起，就算2012年经济景气了，筹集资金不过万把亿，这点小钱其实单凭我们帝国自己就可以埋单嘛。
然后是背景。
《2012》的背景是玛雅预言，这个预言并非宗教产物，而是由一个非常华丽的历法计算出的，玛雅的历法是世界上最精确的历法之一，比儒略历早600年以上，玛雅人日常使用的历法由一个260天历和一个365天历共同组成，前者称作Tzolkin，以13天为一个单位，称作Trecena，20个Trecena为一年；后者称作Haab，以20天为一个单位，称作Veintena，一年为18个Veintena加上5个Wayeb日，这两套历法结合起来给每天起名字，可以保证18980天（也就是52个Haab年）没有重复，超出那个时候人的平均寿命，由于这套历法只适合计日而不适合计年，玛雅人在记录历史时会使用数列来表示年份，通常包含5位，换算成天的方式是：a*18*20^3 + b*18*20^2 + c*18*20 + d*20 + e，其中最高位叫作Baktun，计数方式是13,1,2,3&#8230;,11,12，所以玛雅的创世日记为13.0.0.0.0，按照GMT换算法，下一个13.0.0.0.0就是2012年12月21日。
这里有一个用python写的玛雅历换算工具：http://www.pauahtun.org/Calendar/tools.html ，比如我的生日1984年6月14日，在玛雅历里是12.18.11.1.1（妈的怎么这么多1呀！难道是在预言我的宿命就是单身么！）……在Tzolkin历里是第一个月：Imix （我靠好强大，Tzolkin的260天貌似就是指一个分娩周期），在Haab历里是第4个月：Sotz （哎可惜，要是生在那个5天的Wayeb月就能获得优越感了……）
这个玛雅历中的特殊年份在西方人眼里可能还有两种意义，一个是著名的占星术士诺查丹玛斯（Nostradamus），他预言1999年是世界末日，而据说他那些已经验证过的其他预言，最大误差不超过13年，正好是2012。另一个原因是基督教，众人皆知旧约的创世纪（Genesis）里有诺亚方舟的故事，但这里面有一个很诡异的地方，根据我常用的KJV版（King James钦定版），Genesis 7:4的原文是：
For yet seven days, and I will cause it to rain upon the earth forty days and forty nights; 
以God的第一人称提到了“七天”。然后问题出在《彼得后书》（Second Epistle of Peter），3:5到3:7的原文：
For this they willingly are ignorant of, that by the word of God the heavens were of old, [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2009/11/14/mayan2012/screen-shot-2009-11-14-at-72113-ampng-2/' rel='attachment wp-att-247' title='screen-shot-2009-11-14-at-72113-am.png'><img src='http://www.limboy.com/wp-content/uploads/2009/11/screen-shot-2009-11-14-at-72113-am.png' alt='screen-shot-2009-11-14-at-72113-am.png' style="float:left;width:220px;margin:0 10px 5px 0"  /></a><a href="http://www.mtime.com/movie/80706/" target="_blank" >《2012》</a>最大的缺点还是世界毁灭的太快了，悬念做的不够，我更喜欢cloverfield那种调调，此外视觉效果还是有点单调，这年头只靠一个卷起肯尼迪航母的海啸背景已经唬不住人了，观众眼里尽是绿幕。不过要求太高也是不厚道的，总体来说，《2012》只要把那些传统的美式英雄主义和小范围人道主义的部分剪掉换成特效就相当完美叻！ </p>
<p>先说几个细节：<br />
　　<br />
1，好莱坞影片里常见的mac笔记本，这次完全没有看到，VAIO则至少清晰的出现了5次，主角之一的科学家和白宫官员都用sony笔记本，此外加长林肯在主角逃出加州过程中的表现很明显的说明福特也是出过钱的。<br />
　　<br />
2，黄石公园的超级火山喷发让华盛顿特区进入核冬天，我感觉这个不太靠谱，要吸收大部分太阳辐射的能量，浮尘的直径至少要能小于远红外的波长，也就是13微米，核爆可以做到，而火山灰貌似达不到这个程度。<span id="more-245"></span><br />
　　<br />
3，通过各国领袖在方舟上进行的表决，我们可以发现：3亿人口的美国独占了一艘船，13亿中国人翰1亿多日本人还有可以忽略的俄国人共用另一艘船，5亿人口的EU占了第三艘船——棒子和阿三明显被抛弃了。而非洲由于陆地上升，反而损失相对较小，重新成为人类发源地，这充分说明出来混迟早要还 XD<br />
　　<br />
4，US军方感叹：选中国没错，只有中国能完成这样的工程。其实中国的优势不光是那些继承能吃苦、能战斗、能奉献的优良传统，一切听党指挥的工人兄弟——登上方舟的船票价格是10亿欧元，按照<a target="_blank" href="http://www.forbes.com/2009/03/11/worlds-richest-people-billionaires-2009-billionaires_land.html">09年的水平</a>，全球只有790多位大爷买得起，就算2012年经济景气了，筹集资金不过万把亿，这点小钱其实单凭我们帝国自己就可以埋单嘛。</p>
<p>然后是背景。</p>
<p>《2012》的背景是玛雅预言，这个预言并非宗教产物，而是由一个非常华丽的历法计算出的，玛雅的历法是世界上最精确的历法之一，比儒略历早600年以上，玛雅人日常使用的历法由一个260天历和一个365天历共同组成，前者称作Tzolkin，以13天为一个单位，称作Trecena，20个Trecena为一年；后者称作Haab，以20天为一个单位，称作Veintena，一年为18个Veintena加上5个Wayeb日，这两套历法结合起来给每天起名字，可以保证18980天（也就是52个Haab年）没有重复，超出那个时候人的平均寿命，由于这套历法只适合计日而不适合计年，玛雅人在记录历史时会使用数列来表示年份，通常包含5位，换算成天的方式是：a*18*20^3 + b*18*20^2 + c*18*20 + d*20 + e，其中最高位叫作Baktun，计数方式是13,1,2,3&#8230;,11,12，所以玛雅的创世日记为13.0.0.0.0，按照GMT换算法，下一个13.0.0.0.0就是2012年12月21日。</p>
<p>这里有一个用python写的玛雅历换算工具：<a target="_blank" href="http://www.pauahtun.org/Calendar/tools.html">http://www.pauahtun.org/Calendar/tools.html</a> ，比如我的生日1984年6月14日，在玛雅历里是12.18.11.1.1（妈的怎么这么多1呀！难道是在预言我的宿命就是单身么！）……在Tzolkin历里是第一个月：Imix （我靠好强大，Tzolkin的260天貌似就是指一个分娩周期），在Haab历里是第4个月：Sotz （哎可惜，要是生在那个5天的Wayeb月就能获得优越感了……）</p>
<p>这个玛雅历中的特殊年份在西方人眼里可能还有两种意义，一个是著名的占星术士诺查丹玛斯（Nostradamus），他预言1999年是世界末日，而据说他那些已经验证过的其他预言，最大误差不超过13年，正好是2012。另一个原因是基督教，众人皆知旧约的创世纪（Genesis）里有诺亚方舟的故事，但这里面有一个很诡异的地方，根据我常用的KJV版（King James钦定版），Genesis 7:4的原文是：</p>
<blockquote><p>For yet seven days, and I will cause it to rain upon the earth forty days and forty nights; </p></blockquote>
<p>以God的第一人称提到了“七天”。然后问题出在《彼得后书》（Second Epistle of Peter），3:5到3:7的原文：</p>
<blockquote><p>For this they willingly are ignorant of, that by the word of God the heavens were of old, and the earth standing out of the water and in the water</p>
<p>Whereby the world that then was, being overflowed with water, perished</p>
<p>But the heavens and the earth, which are now, by the same word are kept in store, reserved unto fire against the day of judgment and perdition of ungodly men.</p></blockquote>
<p>大致上就是说世界是按照神的指令，从水中诞生，神要毁灭世界时，就会让水重新覆盖世界，目前天和地还根据当初的指令继续存在，直到开始审判和毁灭那些不信神的人的日子，会“reserved unto fire”，沉沦到火焰之中</p>
<p>很明显是一段警告，而下一段3:8的原文是：</p>
<blockquote><p>But, beloved, be not ignorant of this one thing, that one day is with the Lord as a thousand years, and a thousand years as one day.</p></blockquote>
<p>不要忘记一件事：主视一日如千年，视千年如一日。</p>
<p>我们都知道神在第7天不愿意加班，那么第6天就该开始毁灭世界了罢，<del datetime="2009-11-13T20:27:53+00:00">否则项目就要延期了</del>，在此之前有5天也就是5000年时间，而很多历史研究表明诺亚那次的大洪水发生在公元前3000年左右…… </p>
<p>其实说到神的创世和对人类的惩罚，我很难不联想到最近玩的<a  target="_blank" href="http://www.limboy.com/2009/01/20/dragon_age_is_the_song_of_ice_and_fire/">Dragon Age: Origins</a>，这个游戏的历史设定很有趣：只有一个创世神，称作Maker，他最先创造的世界叫fade，居民叫spirit，这个世界的形态不定，受意识影响，居民也很强大，却没有想象力和创造力，Maker不满意，又创造了另一个物质世界，它没有fade那么“美好”，有固定的形态和法则，却可以在其居民（人类精灵矮人）的努力下不断发展。物质世界和fade世界中间有veil阻挡，不能随意穿越，但是物质世界的生物可以通过做梦的形式，让自己的精神进入fade，Maker还在fade里建造了自己的住所黄金之城（the Golden City），也就是天堂，物质世界里信神的生物死后可以在这里跟主子一起享福。fade里的spirit有善良的也有邪恶，邪恶的就是恶魔，他们嫉妒物质世界的生物，诱惑那些做梦的人，于是人类学会了魔法，建立了一统天下的魔法帝国Tevinter，帝国的法师（Magister）越来越自傲，欲望越来越大，终于有一天他们把手伸向天堂，企图以肉身进入黄金之城，这个行为导致神离开了世界，抛弃了自己的造物，黄金之城堕落为黑城（the Black City），不再有天堂接纳死去的凡人，他们的灵魂只能永远在fade游荡。而那些法师被诅咒转变成了怪物，当他们回到物质世界时，差点毁灭了帝国，历史上称作第一次枯潮（Darkspawn）</p>
<blockquote><p>The mages had sought to usurp Heaven, but instead they destroyed it.</p></blockquote>
<p>相比起遮遮掩掩模棱两可的基督教文献，奇幻游戏的故事要丰满的多，寓意也更明显。所以我觉得很适合作为一篇灾难片评论的结尾。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/11/14/mayan2012/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>我觉得做NARUTO TV动画的人应该切腹</title>
		<link>http://www.limboy.com/2009/09/20/naruto-tv-sucks/</link>
		<comments>http://www.limboy.com/2009/09/20/naruto-tv-sucks/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 15:45:48 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[代码]]></category>
		<category><![CDATA[动漫]]></category>
		<category><![CDATA[土豆网]]></category>
		<category><![CDATA[日漫]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[音乐]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/09/20/naruto-tv-sucks/</guid>
		<description><![CDATA[虽然早在火影沦为四大民工漫之首的若干年前，我就已经没怎么追了（漫画偶尔看看），但是早期几个章节的tv动画（比如卡卡西vs再不斩，中忍考试李洛克vs我爱罗）曾经让我非常非常感动，我不是指那些纠结的人性和搅基的情感之类的玩意让我感动，是指镜头变化和速度感都非常华丽的打斗场面，最近的一部能让我有类似热血感觉的作品是BONES的SOUL EATER。
那段时期大概也是西尾铁也和他手下那帮超强的作画人员还在全力参与的阶段，西尾铁也这个人在国内不算出名，但是他参与过原画的几乎全是神作：《攻壳机动队SAC GIG》，《交响诗篇eureka7》，《精灵守护者》，《东之伊甸》（刚完结，前段时间最喜欢的），押井守最近的剧场动画《空中杀手》（The Sky Crawlers）的人设也是他，主要人物的脸和身体就像火影里一样圆润……


Rock Lee vs 我爱罗的一个MAD版

精灵守护者里的第一场打斗片段

精灵守护者里评价最高的打斗片段

西尾铁也并不是一个人在战斗，他的背后是日本最强（在西方人眼里，对我来说只能算“之一”，BONES，MADHOUSE等公司也能保证必出精品）的动画公司IG，跟他同级别能保证作品质量的强者还有：沖浦啓之（罗德斯岛战记原画，MEMORIES原画，攻壳GIS作画监督，COWBOY BEBOP剧场版OP分镜，演出和原画），黄瀬和哉（天空战记作画监督，EVA TV/旧剧场版/新剧场版作画监督，浪客剑心原画，攻壳SAC SSS原画），此三人合称IG作画三大神。他们参与过的神作不止这些，我只拿自己熟悉的举例。

Cowboy Bebop剧场版天国之扉的op《Ask DNA》，菅野洋子作曲
实际上早期的火影创作团队简直是精英云集，比如音乐是由天才作曲家増田俊郎（他为《虫师》创作的两张碟可能更有名）和擅长日本民俗乐器的摇滚乐队“六三四Musashi”（演奏尺八的那位：http://www.douban.com/subject/2213500/）合作的，包括前三张OST专辑，我最喜欢其中的摇滚部分，比如OST1里的Need To Be Strong和OST3里的自来也主题。

自来也主题曲
但是像西尾这样的人才不可能一直把精力花在柯南般的没完没了的国民动画上，再加上投入的成本大幅降低，为避免进度赶上漫画而搞出的大量脑残般的回忆段落和原创剧情，早期那些热血的动作场面和CG再也看不到了……后期的火影tv版给我的最深刻印象是：主角们在树和树之间跳跃可以花上几十分钟的片长，其滞空时间和思维活动的复杂深邃，远远胜过当年灌篮高手在角色跳投或抢篮板过程中让观众发表五分钟评论的场面。
昨天晚上哥很寂寞，一边看书一边在台式机的chrome上挂豆丸，无意中发现火影最新的OP《萤之光》很好听（可能是因为结合了画面才好听，生物股长这个乐队在红白歌会里看到过，没什么特殊印象），在豆丸里切换了几个相关视频，发现一个MAD版本（MAD即MADMOVIE，这个词起源很宅，反正在日本动漫社区里指二次创作影像），大部分画面是从PS3游戏Naruto: Ultimate Ninja Storm里剪辑出来的，身为一个没买过任何次世代主机被别人主动赠与X360长达两周时间连GTA4都没通关的坚定的久经考验的PC玩家，当时我就震精了……靠这战斗画面太华丽了口牙！速度感满分（比如阿斯玛的斩击，日向雏田的八卦六十四掌），还表现出了漫画里没出现过传说中的技能（四代火影的时空忍术，效果确实像金色闪光）。相比之下现在的动画究竟算什么水平口牙！为什么差距这么大，难道就因为南梦宫更有钱么（纠正……好像是开发.hack的那个工作室搞的），关键还是认真的充满爱的态度罢！
视频来源是niconico，土豆上只能找到三部，基本上所有人物都出场了，优酷上搜不到：





然则画面实在是太模糊了，土豆的MPS系统应该不至于把好片源压成这个鬼样子，因此，这就是我写这篇blog的目的叻！虽然你看完之后可能以为我在发软文……咳……但是……人家没有骗你～人家真的就是想知道这个视频的出处地址或者其他清晰版本嘛～～跪求！（我把别人以前共享的niconico帐号给忘了T___T）
P.S. 最后我要指出……在写这篇blog的时间内很轻松的搜出以上关键词比较特殊的视频，感觉土豆自己研发的搜索系统还是蛮好用的喔活活活活……唯一失败的是soul eater的打斗片段……如果在youtube上搜索“Mifune vs Blackstar”，一定是大把的两三分钟左右的片段，而国内视频用户上传的几乎全是25分钟左右的完整动画……汗……
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/2009/09/20/naruto-tv-sucks/rock_leepng/' rel='attachment wp-att-244' title='rock_lee.png'><img src='http://www.limboy.com/wp-content/uploads/2009/09/rock_lee.png' alt='rock_lee.png' style="margin:0 10px;float:left;width:150px;border:0" /></a>虽然早在火影沦为四大民工漫之首的若干年前，我就已经没怎么追了（漫画偶尔看看），但是早期几个章节的tv动画（比如卡卡西vs再不斩，中忍考试李洛克vs我爱罗）曾经让我非常非常感动，我不是指那些纠结的人性和搅基的情感之类的玩意让我感动，是指镜头变化和速度感都非常华丽的打斗场面，最近的一部能让我有类似热血感觉的作品是BONES的SOUL EATER。</p>
<p>那段时期大概也是西尾铁也和他手下那帮超强的作画人员还在全力参与的阶段，西尾铁也这个人在国内不算出名，但是他参与过原画的几乎全是神作：《攻壳机动队SAC GIG》，《交响诗篇eureka7》，《精灵守护者》，《东之伊甸》（刚完结，前段时间最喜欢的），押井守最近的剧场动画《空中杀手》（The Sky Crawlers）的人设也是他，主要人物的脸和身体就像火影里一样圆润……<span id="more-243"></span></p>
<div style="clear:left;">
<p><object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/LQ3MzZhB62o"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/LQ3MzZhB62o" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object><br />
<em>Rock Lee vs 我爱罗的一个MAD版</em></p>
<p><object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/qKYKfAmdlfE"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/qKYKfAmdlfE" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object><br />
<em>精灵守护者里的第一场打斗片段</em></p>
<p><object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/n691HdFt-ak"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/n691HdFt-ak" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object><br />
<em>精灵守护者里评价最高的打斗片段</em>
</div>
<p>西尾铁也并不是一个人在战斗，他的背后是日本最强（在西方人眼里，对我来说只能算“之一”，BONES，MADHOUSE等公司也能保证必出精品）的动画公司IG，跟他同级别能保证作品质量的强者还有：沖浦啓之（罗德斯岛战记原画，MEMORIES原画，攻壳GIS作画监督，COWBOY BEBOP剧场版OP分镜，演出和原画），黄瀬和哉（天空战记作画监督，EVA TV/旧剧场版/新剧场版作画监督，浪客剑心原画，攻壳SAC SSS原画），此三人合称IG作画三大神。他们参与过的神作不止这些，我只拿自己熟悉的举例。</p>
<p><object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/cX7LR76ik2g"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/cX7LR76ik2g" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object><br />
<em>Cowboy Bebop剧场版天国之扉的op《Ask DNA》，菅野洋子作曲</em></p>
<p>实际上早期的火影创作团队简直是精英云集，比如音乐是由天才作曲家増田俊郎（他为《虫师》创作的两张碟可能更有名）和擅长日本民俗乐器的摇滚乐队“六三四Musashi”（演奏尺八的那位：<a href="http://www.douban.com/subject/2213500/" target="_blank">http://www.douban.com/subject/2213500/</a>）合作的，包括前三张OST专辑，我最喜欢其中的摇滚部分，比如OST1里的Need To Be Strong和OST3里的自来也主题。</p>
<p><object width="420" height="30"><param name="movie" value="http://www.tudou.com/v/1aV_pEi2ix4"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/1aV_pEi2ix4" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="30"></embed></object><br />
<em>自来也主题曲</em></p>
<p>但是像西尾这样的人才不可能一直把精力花在柯南般的没完没了的国民动画上，再加上投入的成本大幅降低，为避免进度赶上漫画而搞出的大量脑残般的回忆段落和原创剧情，早期那些热血的动作场面和CG再也看不到了……后期的火影tv版给我的最深刻印象是：主角们在树和树之间跳跃可以花上几十分钟的片长，其滞空时间和思维活动的复杂深邃，远远胜过当年灌篮高手在角色跳投或抢篮板过程中让观众发表五分钟评论的场面。</p>
<p>昨天晚上<del>哥很寂寞</del>，一边看书一边在台式机的chrome上挂<a href="http://douwan.tudou.com" target="_blank">豆丸</a>，无意中发现火影最新的OP《萤之光》很好听（可能是因为结合了画面才好听，生物股长这个乐队在红白歌会里看到过，没什么特殊印象），在豆丸里切换了几个相关视频，发现一个MAD版本（MAD即MADMOVIE，这个词起源很宅，反正在日本动漫社区里指二次创作影像），大部分画面是从PS3游戏<a href="http://ps3.ign.com/articles/867/867121p1.html" target="_blank">Naruto: Ultimate Ninja Storm</a>里剪辑出来的，身为一个没买过任何次世代主机被别人主动赠与X360长达两周时间连GTA4都没通关的坚定的久经考验的PC玩家，当时我就震精了……靠这战斗画面太华丽了口牙！速度感满分（比如阿斯玛的斩击，日向雏田的八卦六十四掌），还表现出了漫画里没出现过传说中的技能（四代火影的时空忍术，效果确实像金色闪光）。相比之下现在的动画究竟算什么水平口牙！为什么差距这么大，难道就因为<del>南梦宫更有钱么</del>（纠正……好像是开发.hack的那个工作室搞的），关键还是认真的充满爱的态度罢！</p>
<p>视频来源是niconico，土豆上只能找到三部，基本上所有人物都出场了，优酷上搜不到：</p>
<p><object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/orxR5UdpLQE"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/orxR5UdpLQE" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object><br />
<br/><br />
<object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/pbnBfT4a25Y"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/pbnBfT4a25Y" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object><br />
<br/><br />
<object width="420" height="363"><param name="movie" value="http://www.tudou.com/v/tfJv8DJeNHs"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><embed src="http://www.tudou.com/v/tfJv8DJeNHs" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="420" height="363"></embed></object></p>
<p>然则画面实在是太模糊了，土豆的MPS系统应该不至于把好片源压成这个鬼样子，因此，这就是我写这篇blog的目的叻！虽然你看完之后可能以为我在发软文……咳……但是……人家没有骗你～人家真的就是想知道这个视频的出处地址或者其他清晰版本嘛～～跪求！（我把别人以前共享的niconico帐号给忘了T___T）</p>
<p>P.S. 最后我要指出……在写这篇blog的时间内很轻松的搜出以上关键词比较特殊的视频，感觉土豆自己研发的搜索系统还是蛮好用的喔活活活活……唯一失败的是soul eater的打斗片段……如果在youtube上搜索“Mifune vs Blackstar”，一定是大把的两三分钟左右的片段，而国内视频用户上传的几乎全是25分钟左右的完整动画……汗……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/09/20/naruto-tv-sucks/feed/</wfw:commentRss>
		<slash:comments>1</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>twitter like和传统论坛</title>
		<link>http://www.limboy.com/2009/05/16/forum2twitter/</link>
		<comments>http://www.limboy.com/2009/05/16/forum2twitter/#comments</comments>
		<pubDate>Sat, 16 May 2009 07:20:11 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Web2.0]]></category>
		<category><![CDATA[web服务/应用]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[日漫]]></category>
		<category><![CDATA[网络]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/05/16/forum2twitter/</guid>
		<description><![CDATA[以前字符姐姐说我和绯雨叔叔都是彼得潘，另外我还以腹黑正太闻名，但是我也不得不承认，时间既是最难战胜的敌人也是最有价值的财富。如今面临的困扰，就是上网习惯变化很大，虽然firefox的书签工具栏上依然保留了很多论坛的链接（不常上的网站我都放到delicious里），但是别说跟人论战，就连踩遍各大论坛的时间也没有叻。我现在更习惯阅读feed（通过google reader和igoogle，后者类似报纸的体验）以及twitter模式的推送信息（通过桌面客户端和像friendfeed那样实时更新的网页）。
但是支持这种阅读习惯的环境却不是很理想（对国内而言）——SNS/twitter里的信息价值不高，多数都是缺少上下文的唠叨和零碎的感悟，以及只有熟人会感兴趣的琐事和闲扯；个人博客的内容同质化严重，而且热度早已降温，更新频率普遍下降（我除外喔，我更新一直都这么少XD）。大量有价值的信息仍然深藏在论坛和社区网站（其中我最反感的形式是通过积分或虚拟货币的形式设定阅读权限，人为阻止信息传播和再利用），没有进入社会化网络。其实我大学时做的最深的地下城，也出于类似的考虑：很多有价值的信息隐藏在论坛这种“深层网络”（或者叫黯网络罢~）中，只被社区内部的核心成员所熟悉，虽然这样能把讨论维持在较高的质量，也能保证读者跟作者的直接联系，但是如果能借助更开放更易于接触的平台来传播，原本可以影响到更多人。

插图：这张图是我的书签工具栏，除了这个地方，书签的其他位置不放东西，也就是让真正的常用网站都位于随手可点的位置，不常用的网站扔到另一个管理体系里
不过幸好技术的普及速度永远比用户习惯的迁移要快，现在很多论坛都开始提供feed了（感谢Discuz!），借助friendfeed就可以很好的转换成推送信息。
也就是在friendfeed里建一个group，把feed用custom rss/atom或blog的形式导入进去，并且勾选“Include entry description as a comment”，也就是把rss里的描述节点转换成friendfeed里的评论（毕竟仅凭一个标题链接，很难决定是否深入阅读）。然后设置deliver为IM方式，便可以通过gtalk接收信息了，感觉跟IRC或群差不多~
缺点是导入的评论全都会算到自己头上……
另外由于论坛feed通常只包含新主题，如果是像过去的NT那样，大家都愿意在十几页的回帖里长篇大论的拍砖并且跑题现象严重的论坛，就很难track到有价值的内容，不过对于那样的论坛，直接参与才是更好的阅读方式罢
这个是我刚刚弄的一个聚合，收集web前端技术的资讯和资源：
https://friendfeed.com/frontend-feed-cn
这个效果也很不错，track国内的SF/F社区：
https://friendfeed.com/fantasycn
但是接下来的计划就麻烦了…动漫方面，破狗，云中之类的论坛都没feed（用VBB不是错，但是要升级到新版哑！）
还想搞一个pc game的，但是TLF，NGA之类的站帖子太多……指挥官，铁资网之类的论坛也是没feed……让我感觉有折腾这个的工夫，还不如去打demigod……
柠檬基拉老爷提醒说有很多网页转rss的工具，这个我以前确实见过很多但都没怎么体验过，想来也不太靠谱………其实我觉得，一个真正的强者，在这种情况下就应该挺身而出，开发出一个兼具抓取，聚合，呈现，通知等功能的web应用，来满足自己的需求……当然由于我最近很懒，这个idea由我来实现的可能性小于10%罢……
我还是希望有更多社区网站都能以开放的心态，把自己的内容用更友善更易于传播的形式输出，开放永远是互联网的根基，而后web2.0时代的互联网应该是有机的整体，内容在一个站点产出后，可以通过“云”的加工变得更易于查找，更易于阅读，更易于传播，而互联网用户则能接触到更广阔更个性化的信息。
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;肆无忌惮跑题的分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
PS：题图是我最近在追的新番《东之伊甸》，要素是：近未来，游戏规则，社会弊端，写实的科技应用（围绕手机），对西方电影的引用，整体风格非常像攻壳SAC，可惜……好像只会有11话，单季都不够哑！神山健治老师请多做一些类攻壳的作品罢！
另外最近还在追《苍天航路》，要素是气势！无论人物，动作，姿态，对话，打斗场面，都燃的像港漫，我觉得多看这个一定能改善我最近多愁善感的非主流形象，成为无所畏惧的强者挖哈哈哈哈哈哈～

]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2009/05/picture-5.png' title='picture-5.png' ><img src='http://www.limboy.com/wp-content/uploads/2009/05/picture-5.png' alt='picture-5.png' style="width:250px;float:left;margin:0 10px 10px 0"  /></a>以前字符姐姐说我和<a target="_blank"  href="http://blog.sina.com.cn/five_fire">绯雨叔叔</a>都是彼得潘，另外我还以腹黑正太闻名，但是我也不得不承认，时间既是最难战胜的敌人也是最有价值的财富。如今面临的困扰，就是上网习惯变化很大，虽然firefox的书签工具栏上依然保留了很多论坛的链接（不常上的网站我都放到delicious里），但是别说跟人论战，就连踩遍各大论坛的时间也没有叻。我现在更习惯阅读feed（通过google reader和igoogle，后者类似报纸的体验）以及twitter模式的推送信息（通过桌面客户端和像friendfeed那样实时更新的网页）。</p>
<p>但是支持这种阅读习惯的环境却不是很理想（对国内而言）——SNS/twitter里的信息价值不高，多数都是缺少上下文的唠叨和零碎的感悟，以及只有熟人会感兴趣的琐事和闲扯；个人博客的内容同质化严重，而且热度早已降温，更新频率普遍下降（我除外喔，我更新一直都这么少XD）。大量有价值的信息仍然深藏在论坛和社区网站（其中我最反感的形式是通过积分或虚拟货币的形式设定阅读权限，人为阻止信息传播和再利用），没有进入社会化网络。<span id="more-224"></span>其实我大学时做的最深的地下城，也出于类似的考虑：很多有价值的信息隐藏在论坛这种“深层网络”（或者叫黯网络罢~）中，只被社区内部的核心成员所熟悉，虽然这样能把讨论维持在较高的质量，也能保证读者跟作者的直接联系，但是如果能借助更开放更易于接触的平台来传播，原本可以影响到更多人。</p>
<p><a href='http://www.limboy.com/wp-content/uploads/2009/05/picture-3.png' title='picture-3.png'><img src='http://www.limboy.com/wp-content/uploads/2009/05/picture-3.png' alt='picture-3.png' style="width:400px;" /></a><br />
<strong>插图：</strong><em>这张图是我的书签工具栏，除了这个地方，书签的其他位置不放东西，也就是让真正的常用网站都位于随手可点的位置，不常用的网站扔到另一个管理体系里</em></p>
<p>不过幸好技术的普及速度永远比用户习惯的迁移要快，现在很多论坛都开始提供feed了（感谢Discuz!），借助<a target="_blank" href="https://friendfeed.com/dexteryy">friendfeed</a>就可以很好的转换成推送信息。</p>
<p>也就是在friendfeed里建一个group，把feed用custom rss/atom或blog的形式导入进去，并且勾选“Include entry description as a comment”，也就是把rss里的描述节点转换成friendfeed里的评论（毕竟仅凭一个标题链接，很难决定是否深入阅读）。然后设置deliver为IM方式，便可以通过gtalk接收信息了，感觉跟IRC或群差不多~</p>
<p>缺点是导入的评论全都会算到自己头上……</p>
<p>另外由于论坛feed通常只包含新主题，如果是像过去的NT那样，大家都愿意在十几页的回帖里长篇大论的拍砖并且跑题现象严重的论坛，就很难track到有价值的内容，不过对于那样的论坛，直接参与才是更好的阅读方式罢</p>
<p>这个是我刚刚弄的一个聚合，收集web前端技术的资讯和资源：</p>
<p><a target="_blank" href="https://friendfeed.com/frontend-feed-cn"><img src="http://i.friendfeed.com/p-8575630059de44aeb0762dfce50426e7-large-1" style="margin:0 10px 0 0;border:0;" /></a><a target="_blank" href="https://friendfeed.com/frontend-feed-cn">https://friendfeed.com/frontend-feed-cn</a></p>
<p>这个效果也很不错，track国内的SF/F社区：</p>
<p><a target="_blank" href="https://friendfeed.com/fantasycn"><img src="http://i.friendfeed.com/p-8dacd5026ef848338eefe0abaf892cb5-large-1" style="margin:0 10px 0 0;border:0;" /></a><a target="_blank" href="https://friendfeed.com/fantasycn">https://friendfeed.com/fantasycn</a></p>
<p>但是接下来的计划就麻烦了…动漫方面，<a target="_blank" href="http://bbs.popgo.net/bbs/">破狗</a>，<a target="_blank" href="http://www.cloudc.net/cgi-bin/bbs/index.cgi">云中</a>之类的论坛都没feed（用VBB不是错，但是要升级到新版哑！）</p>
<p>还想搞一个pc game的，但是<a target="_blank"  href="http://www.eastgame.net/">TLF</a>，<a target="_blank"  href="http://bbs.ngacn.cc/">NGA</a>之类的站帖子太多……<a  target="_blank" href="http://zhihuiguan.com/bbs/">指挥官</a>，<a  target="_blank" href="http://tbsgame.net/bbs/">铁资网</a>之类的论坛也是没feed……让我感觉有折腾这个的工夫，还不如去打demigod……</p>
<p><a target="_blank" href="http://twitter.com/lemonkiller/status/1808532539">柠檬基拉</a>老爷提醒说有很多网页转rss的工具，这个我以前确实见过很多但都没怎么体验过，想来也不太靠谱………其实我觉得，一个真正的强者，在这种情况下就应该挺身而出，开发出一个兼具抓取，聚合，呈现，通知等功能的web应用，来满足自己的需求……当然由于我最近很懒，这个idea由我来实现的可能性小于10%罢……</p>
<p>我还是希望有更多社区网站都能以开放的心态，把自己的内容用更友善更易于传播的形式输出，开放永远是互联网的根基，而后web2.0时代的互联网应该是有机的整体，内容在一个站点产出后，可以通过“云”的加工变得更易于查找，更易于阅读，更易于传播，而互联网用户则能接触到更广阔更个性化的信息。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;肆无忌惮跑题的分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>PS：题图是我最近在追的新番《东之伊甸》，要素是：近未来，游戏规则，社会弊端，写实的科技应用（围绕手机），对西方电影的引用，整体风格非常像攻壳SAC，可惜……好像只会有11话，单季都不够哑！神山健治老师请多做一些类攻壳的作品罢！</p>
<p>另外最近还在追《苍天航路》，要素是气势！无论人物，动作，姿态，对话，打斗场面，都燃的像港漫，我觉得多看这个一定能改善我最近多愁善感的非主流形象，成为无所畏惧的强者挖哈哈哈哈哈哈～</p>
<p><a href='http://www.limboy.com/wp-content/uploads/2009/05/picture-7.png' title='picture-7.png'><img src='http://www.limboy.com/wp-content/uploads/2009/05/picture-7.png' alt='picture-7.png' style="width:400px;" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/05/16/forum2twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>每个成功的社区背后都有一个教主——评solidot的浏览器连接数事件</title>
		<link>http://www.limboy.com/2009/02/08/troll_in_solidot/</link>
		<comments>http://www.limboy.com/2009/02/08/troll_in_solidot/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 09:05:00 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[Firefox]]></category>
		<category><![CDATA[kuso]]></category>
		<category><![CDATA[科技]]></category>
		<category><![CDATA[纯水]]></category>
		<category><![CDATA[网络]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/02/08/troll_in_solidot/</guid>
		<description><![CDATA[我就一直很羡慕国外技术社区reddit和slashdot的评论，无论数量还是质量，无论趣味性还是信息含量，都让国内的网站相形见绌——先声明一下我绝对没有拿国内评论方面最火的cnbeta来比较喔，它们看上去根本不属于同一个位面……
我也经常看国内的solidot，时间长了都能猜出某篇文章会不会有评论，从google reader里点过去看，命中率相当高，这些文章通常就涉及那么几个话题，比如操作系统，比如国内it企业的丑闻，比如抨击zf针砭时弊，这种现象很好理解喔，毕竟年纪大点的人都更关心跟自己生活关系紧密的东西，而且这些话题的门槛也比较低，对国内网民来说，太geek的东西相当于太阳春白雪，应者寥寥，那是宿命～
但是今天我对solidot的印象大为改观！就在我下午昏昏欲睡不抱期望的点开一个帖子之后，意外的发现了非常娱乐非常有信息量的评论——说的更直接点，是发现了一个有教主潜质的用户：cuthead。这位老爷必将拯救solidot！实际上他如果不在技术圈混，转战天涯S1之类的地方，定能跻身年度强者哑！
你可以按照我的阅读顺序来观摩这个从1月16日发展到前天的，非常戏剧性的事件：
1，solidot《BT大站海盗湾提供下载者地理分布图》, 从lark的评论#32105和cuthead的回复#32111开始
2，moztw论坛《Firefox并发连接数限制是针对网址还是针对服务器IP？》，看到台湾的Dark Shenada的第一个回复和cuthead的反应为止
3，solidot 《Ubuntu下的网速快过XP》，从#31504开始～
4，贴吧《firefox 连接数限制分析》，看完这个再回头来继续看moztw论坛《Firefox并发连接数限制是针对网址还是针对服务器IP？》
好罢其实真正的时间顺序是3,2,1,4……
下面按照时间顺序收集cuthead老爷的语录——不好意思这是教主的传统待遇了，旧习惯改不了……
教主找茬：
我以前的评论有没有犯过这么明显的错误？
教主既淡定又超然：

没意思，我不是给你出脑筋急转弯那个初级阶段了，我是向你赔礼道歉来了！三年了，在这个世界上最对不起的人就是范厨师，多么好的人，我常跟你们说，你说我忽悠他干啥？多么忠厚老实！你打我两下，你下不去手，你骂我两句，你张不开嘴，这样，反正你原谅我也来了，不原谅我也来了，原谅不原谅我都带着诚意铺面而来地！
教主讲解技术：
浏览器连接同一个服务器默认最大连接数不超过10，所以这个限制对网页浏览的影响是0。这也是为什么微软要把TCP并发连接设为10的原因。
教主又超然了：
哈哈，当某些人不喜欢夹着尾巴做人的时候，我也要把尾巴露出来，这是人类的一项本能。
教主愤青了：
你的最后一句话恰恰阐明了我为什么喜欢攻击你们这些语文爱好者。每一个玩文字游戏的人遇到我都应该学会哭泣，我恨所有的现代文学。就像你和那个normalsb,一个喜欢扩写，一个喜欢鸡蛋挑骨头。扩写也就扩写好了，一点新意和技术含量也没有。另一个normalsb更是搞笑，我说浏览器连接同一个服务器默认最大连接数不超过10，他跟我扯子域名和主域名绑定IP可以不同。你们这些牵强的说一些驴唇不对马嘴的废话的scum的存在只能证明一件事情，我的逻辑天衣无缝。另外奉劝你们，这里是solidot，不是电脑城，不要把扯淡的一套拿到这里来和我讨论那些毫无用处的过家家，如果你们真的喜欢废话，这些就是我送你们的压岁钱。
教主急了：
你觉得你水平能赶上我吗？
如果我没错你诬蔑我错的话，我要你的人头落地，你敢跟我打这个赌吗？你还有脸说废话，normalsb也犯了一个明显的错误却不自知。我不知道你们这些扯淡流的话是自己胡编出来还是跟哪个更扯淡的大虾鹦鹉学舌而来，但我的话在网上都可以找到根据。我说浏览器连接同一个服务器默认最大连接数不超过10，我这句话就撂这里了，谁敢用论据反驳？
教主寻求支援：
我多年一直有一個疑問，Firefox並發連接數限制是針對網址還是針對服務器IP？官方網站說的也不清不楚。 
教主觉得mozilla忒傻X怎么搞出这样的命名：
並發連接數是否會超過此参数的限制？ 如果是的話，證明此此参数是用來限制域名的。 但這個參數後面跟的是server而不是site
教主急着等米下锅：
这咋还没人回复呢，是不是大家认为我比较菜所以不屑于回答？其实我也是一个Linux资深用户，刚刚用Windows只是临时的。大家看我帖子底下就全明白了
教主看到想象中的大牛赶紧拍马：
高手，感謝Dark Shenada。看您頭像就知道您不簡單，您的大作我一定會仔細閱讀的。我閱讀英語有輕微障礙，經常需要使用翻譯單詞的bookmarklet，所以 lwn.net這個網站我貌似Delicious過，不過確實沒仔細看。其實我是一個Linux菜鳥，經常被Linux某些難題難住。你也知道在大陸人人都很喜歡裝，我把這壞毛病帶到這裡了。 (也有開玩笑的意思)。當時發帖比較著急所以沒注意字裡行間的問題。 大陸一個人發帖說Firefox是根據網址來限制連接數。我當時很氣憤這人睜眼說瞎話。
拿到“台湾人”的令牌后，教主回来了：
举不出实例就是举不出实例，我特意发到台湾论坛上去了，台湾人说了我是正确的 [moztw.org]。建议你以后说话最好带上良心。哥们我这次放过你，但不代表我认可你令人恶心的行为。你只是在说一些你自己编造的谎言罢了。
教主要求检方举证：
你如果能提供Firefox是根据域名限制并发连接数的英文参考文章链接我就真服了你
教主突然变成“语文爱好者”：
这不是一个链接吧？
教主欣欣然的在其他地方继续找茬：
摆脱你怎么又写出这么多垃圾信息啊？谁问你了？以后你想写垃圾信息麻烦请在地址栏输入 http://tieba.baidu.com/ [baidu.com]
教主得理不饶人：
另外你那个连接数问题，我特意发到台湾论坛上去了，台湾人说了我是正确的 [moztw.org]。建议你以后说话最好带上良心。哥们我这次放过你，但不代表我认可你令人恶心的行为。你如果不是一个程序员就不要指望我以程序员态度对你。
对于之后moztw论坛上的戏剧性发展，教主暂时还没有表示影响不大……
必须承认我实在是太喜欢教主这种时而超然时而愤世嫉俗从不透露真才实学却又不容质疑非常理直气壮非常troll的语气了！

====================论事不论人的分割线======================

另外从这个话题本身来说，我还发现了一个很有趣的差异性：浏览器的连接数限制这个东西是web前端优化里最重要的知识，但是跟这些C/C++程序员不同，多数“前端工程师”都不会对“浏览器根据域名来限制连接数”有任何疑问，更不会像lark这样去看firefox源码来验证，因为……这，这可是“标准”耶！我们只认W3C和IETF的唷！-___-b 
……不过，RFC2612上对“server”的解释，教主老爷真的需要看一下，server并非实体的服务器也并非具体的website，抽象层面没有那么低，其实只是代指一种接受http request返回http response的应用程序而已：
server
An application program that accepts connections in order to service requests by sending back responses. Any given program may be capable of being both a client and a server; our use of these terms refers only [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.limboy.com/2009/02/08/troll_in_solidot/mountaintroll1jpg/" rel="attachment wp-att-220" title="mountaintroll1.jpg"><img src="http://www.limboy.com/wp-content/uploads/2009/02/mountaintroll1.jpg" style="border:0;margin: 0pt 6px 0pt 0pt; width: 210px; float: left;" /></a>我就一直很羡慕国外技术社区<a href="http://www.reddit.com/r/programming/" target="_blank">reddit</a>和<a href="http://slashdot.org/" target="_blank">slashdot</a>的评论，无论数量还是质量，无论趣味性还是信息含量，都让国内的网站相形见绌——先声明一下我绝对没有拿国内评论方面最火的<a href="http://www.cnbeta.com/" target="_blank">cnbeta</a>来比较喔，它们看上去根本不属于同一个位面……</p>
<p>我也经常看国内的<a href="http://www.solidot.org" target="_blank">solidot</a>，时间长了都能猜出某篇文章会不会有评论，从google reader里点过去看，命中率相当高，这些文章通常就涉及那么几个话题，比如操作系统，比如国内it企业的丑闻，比如抨击zf针砭时弊，这种现象很好理解喔，毕竟年纪大点的人都更关心跟自己生活关系紧密的东西，而且这些话题的门槛也比较低，对国内网民来说，太geek的东西相当于太阳春白雪，应者寥寥，那是宿命～</p>
<p>但是今天我对solidot的印象大为改观！就在我下午昏昏欲睡不抱期望的点开一个帖子之后，意外的发现了非常娱乐非常有信息量的评论——说的更直接点，是发现了一个有<a href="http://baike.baidu.com/view/302987.htm" target="_blank">教主潜质</a>的用户<span id="more-221"></span>：cuthead。这位老爷必将拯救solidot！实际上他如果不在技术圈混，转战天涯S1之类的地方，定能跻身年度强者哑！</p>
<p>你可以按照我的阅读顺序来观摩这个从1月16日发展到前天的，非常戏剧性的事件：</p>
<p>1，<a target="_blank" href="http://internet.solidot.org/article.pl?sid=09/02/05/0435224">solidot《BT大站海盗湾提供下载者地理分布图》</a>, 从lark的评论<a target="_blank" href="http://internet.solidot.org/comments.pl?sid=10577&amp;cid=32105">#32105</a>和cuthead的回复<a target="_blank" href="http://internet.solidot.org/comments.pl?sid=10577&amp;cid=32111">#32111</a>开始<br />
2，<a target="_blank" href="http://forum.moztw.org/viewtopic.php?p=142208">moztw论坛《Firefox并发连接数限制是针对网址还是针对服务器IP？》</a>，看到台湾的Dark Shenada的第一个回复和cuthead的反应为止<br />
3，<a target="_blank" href="http://linux.solidot.org/article.pl?sid=09/01/16/066258">solidot 《Ubuntu下的网速快过XP》</a>，从<a target="_blank" href="http://linux.solidot.org/comments.pl?sid=10338&amp;cid=31504">#31504</a>开始～<br />
4，<a href="http://tieba.baidu.com/f?kz=535393925" target="_blank">贴吧《firefox 连接数限制分析》</a>，看完这个再回头来继续看<a target="_blank" href="http://forum.moztw.org/viewtopic.php?p=142208">moztw论坛《Firefox并发连接数限制是针对网址还是针对服务器IP？》</a></p>
<p>好罢其实真正的时间顺序是3,2,1,4……</p>
<p>下面按照时间顺序收集cuthead老爷的语录——不好意思这是教主的传统待遇了，旧习惯改不了……</p>
<p>教主找茬：</p>
<blockquote><p>我以前的评论有没有犯过这么明显的错误？</p></blockquote>
<p>教主既淡定又超然：</p>
<blockquote><p>
没意思，我不是给你出脑筋急转弯那个初级阶段了，我是向你赔礼道歉来了！三年了，在这个世界上最对不起的人就是范厨师，多么好的人，我常跟你们说，你说我忽悠他干啥？多么忠厚老实！你打我两下，你下不去手，你骂我两句，你张不开嘴，这样，反正你原谅我也来了，不原谅我也来了，原谅不原谅我都带着诚意铺面而来地！</p></blockquote>
<p>教主讲解技术：</p>
<blockquote><p>浏览器连接同一个服务器默认最大连接数不超过10，所以这个限制对网页浏览的影响是0。这也是为什么微软要把TCP并发连接设为10的原因。</p></blockquote>
<p>教主又超然了：</p>
<blockquote><p>哈哈，当某些人不喜欢夹着尾巴做人的时候，我也要把尾巴露出来，这是人类的一项本能。</p></blockquote>
<p>教主愤青了：</p>
<blockquote><p>你的最后一句话恰恰阐明了我为什么喜欢攻击你们这些语文爱好者。每一个玩文字游戏的人遇到我都应该学会哭泣，我恨所有的现代文学。就像你和那个normalsb,一个喜欢扩写，一个喜欢鸡蛋挑骨头。扩写也就扩写好了，一点新意和技术含量也没有。另一个normalsb更是搞笑，我说浏览器连接同一个服务器默认最大连接数不超过10，他跟我扯子域名和主域名绑定IP可以不同。你们这些牵强的说一些驴唇不对马嘴的废话的scum的存在只能证明一件事情，我的逻辑天衣无缝。另外奉劝你们，这里是solidot，不是电脑城，不要把扯淡的一套拿到这里来和我讨论那些毫无用处的过家家，如果你们真的喜欢废话，这些就是我送你们的压岁钱。</p></blockquote>
<p>教主急了：</p>
<blockquote><p>你觉得你水平能赶上我吗？</p>
<p>如果我没错你诬蔑我错的话，我要你的人头落地，你敢跟我打这个赌吗？你还有脸说废话，normalsb也犯了一个明显的错误却不自知。我不知道你们这些扯淡流的话是自己胡编出来还是跟哪个更扯淡的大虾鹦鹉学舌而来，但我的话在网上都可以找到根据。我说浏览器连接同一个服务器默认最大连接数不超过10，我这句话就撂这里了，谁敢用论据反驳？</p></blockquote>
<p>教主寻求支援：</p>
<blockquote><p>我多年一直有一個疑問，Firefox並發連接數限制是針對網址還是針對服務器IP？官方網站說的也不清不楚。 </p></blockquote>
<p>教主觉得mozilla忒傻X怎么搞出这样的命名：</p>
<blockquote><p>並發連接數是否會超過此参数的限制？ 如果是的話，證明此此参数是用來限制域名的。 但這個參數後面跟的是server而不是site</p></blockquote>
<p>教主急着等米下锅：</p>
<blockquote><p>这咋还没人回复呢，是不是大家认为我比较菜所以不屑于回答？其实我也是一个Linux资深用户，刚刚用Windows只是临时的。大家看我帖子底下就全明白了</p></blockquote>
<p>教主看到想象中的大牛赶紧拍马：</p>
<blockquote><p>高手，感謝Dark Shenada。看您頭像就知道您不簡單，您的大作我一定會仔細閱讀的。我閱讀英語有輕微障礙，經常需要使用翻譯單詞的bookmarklet，所以 lwn.net這個網站我貌似Delicious過，不過確實沒仔細看。其實我是一個Linux菜鳥，經常被Linux某些難題難住。你也知道在大陸人人都很喜歡裝，我把這壞毛病帶到這裡了。 (也有開玩笑的意思)。當時發帖比較著急所以沒注意字裡行間的問題。 大陸一個人發帖說Firefox是根據網址來限制連接數。我當時很氣憤這人睜眼說瞎話。</p></blockquote>
<p>拿到“台湾人”的令牌后，教主回来了：</p>
<blockquote><p>举不出实例就是举不出实例，我特意发到台湾论坛上去了，台湾人说了我是正确的 [moztw.org]。建议你以后说话最好带上良心。哥们我这次放过你，但不代表我认可你令人恶心的行为。你只是在说一些你自己编造的谎言罢了。</p></blockquote>
<p>教主要求检方举证：</p>
<blockquote><p>你如果能提供Firefox是根据域名限制并发连接数的英文参考文章链接我就真服了你</p></blockquote>
<p>教主突然变成“语文爱好者”：</p>
<blockquote><p>这不是一个链接吧？</p></blockquote>
<p>教主欣欣然的在其他地方继续找茬：</p>
<blockquote><p>摆脱你怎么又写出这么多垃圾信息啊？谁问你了？以后你想写垃圾信息麻烦请在地址栏输入 http://tieba.baidu.com/ [baidu.com]</p></blockquote>
<p>教主得理不饶人：</p>
<blockquote><p>另外你那个连接数问题，我特意发到台湾论坛上去了，台湾人说了我是正确的 [moztw.org]。建议你以后说话最好带上良心。哥们我这次放过你，但不代表我认可你令人恶心的行为。你如果不是一个程序员就不要指望我以程序员态度对你。</p></blockquote>
<p>对于之后moztw论坛上的戏剧性发展，教主暂时还没有表示影响不大……</p>
<p>必须承认我实在是太喜欢教主这种时而超然时而愤世嫉俗从不透露真才实学却又不容质疑非常理直气壮非常<a href="http://en.wikipedia.org/wiki/Internet_troll" target="_blank">troll</a>的语气了！<br />
<br/><br/><br />
====================论事不论人的分割线======================<br />
<br/><br />
另外从这个话题本身来说，我还发现了一个很有趣的差异性：浏览器的连接数限制这个东西是<a target="_blank" href="http://developer.yahoo.com/performance/rules.html#num_http">web前端优化</a>里最重要的知识，但是跟这些C/C++程序员不同，多数“前端工程师”都不会对“浏览器根据域名来限制连接数”有任何疑问，更不会像lark这样去看firefox源码来验证，因为……这，这可是“标准”耶！我们只认W3C和IETF的唷！-___-b </p>
<p>……不过，<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html#sec1.1" target="_blank">RFC2612上对“server”的解释</a>，教主老爷真的需要看一下，server并非实体的服务器也并非具体的website，抽象层面没有那么低，其实只是代指一种接受http request返回http response的应用程序而已：</p>
<blockquote><p>server</p>
<p>An application program that accepts connections in order to service requests by sending back responses. Any given program may be capable of being both a client and a server; our use of these terms refers only to the role being performed by the program for a particular connection, rather than to the program&#8217;s capabilities in general. Likewise, any server may act as an origin server, proxy, gateway, or tunnel, switching behavior based on the nature of each request.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/02/08/troll_in_solidot/feed/</wfw:commentRss>
		<slash:comments>4</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>Dragon Age: Origins其实就是冰与火之歌+博德之门?</title>
		<link>http://www.limboy.com/2009/01/20/dragon_age_is_the_song_of_ice_and_fire/</link>
		<comments>http://www.limboy.com/2009/01/20/dragon_age_is_the_song_of_ice_and_fire/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 19:30:01 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[SF/F]]></category>
		<category><![CDATA[书籍]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2009/01/20/dragon_age_is_the_song_of_ice_and_fire/</guid>
		<description><![CDATA[啊啊啊我现在对这部作品的热情超过辐射3了，Dragon Age: Origins的主旨是“回归原初（Origins）”，Bioware在战术和队友系统上确实是在回归博德之门，但是在剧情和设定方面，完全是在向乔治RR马丁那部被认为能以一抵四（四大名著）的《冰与火之歌》致敬哑！以下是《冰火》里的关键元素和对应的DAO设定：
龙
被认为已经灭绝的巨龙开始重新出现，还以此背景来给游戏命名
异鬼
难以理解的黑暗生物大军（Darkspawn）每隔几百年就大举入侵文明世界，被称作the Blight，而且同样跟远古异神（the Old Gods）有关，入侵方向好像也是由北向南？好像同样是从地下钻出来的？（有人认为《冰火》里的异鬼是野蛮人寻找冬之号角时从古代陵墓里挖出来的……）
守夜人
上古时代的第一次the Blight，无论在物质上还是心理上都造成了难以磨灭的巨大创伤，直接导致帝国毁灭，类似《冰火》的历史里记载的“长夜”，于是后人建立了特殊军事组织Grey Wardens，战时作为与Darkspawn对抗的主力军，和平时期还要负责守护关于那些异界生物的知识，另外，他们跟《冰火》里的守夜人一样被现世的人们忽视，还拥有征募新兵的特权
狼
狼/狼人和狗在文化中有特殊地位（战犬还要占一个队友栏，有机会COS少狼主和Lord Snow了！大心！）
学士
在《冰火》里叫Maester，在DAO里叫Magi， Circle of Magi好像是类似学城的组织
异域民族
Ferelden跟《冰火》里的维斯特洛大陆（Westeros）一样，从世界观的角度来看是主要的大陆，从地理的角度来看只是很小的一块蛮荒之地。不过被遗忘国度里的Faerun在托瑞尔大陆的地位也差不多，西方人经历了数次“世界”的扩大，从地中海周边的罗马帝国，加入阿拉伯，加入远东，加入新大陆……可能形成了根深蒂固的“我们的世界观很狭隘，我们的大陆很蛮荒”的情结……
瓦雷利亚帝国
历史上曾经存在一统天下并且掌握强大魔法力量的Tevinter帝国，在灾变中覆灭，但是现今仍然在地理和文化上留下大量痕迹……（又是西方人的罗马帝国情结……）
黑暗中世纪
完全不像博得之门里那种已经接近蒸汽朋克的高魔世界（我认为超过了被遗忘国度原有的程度），而是类似维斯特洛大陆那种非常野蛮原始，非常现实主义的中世纪风格。官方自称黑暗奇幻（dark fantasy），而冰火正是dark complex epic fantasy
封建领主和政治斗争
Ferelden的基本权力单位是割据各地的小领主（被称作bann），占据重要城堡的贵族地位更高，称作arl，少数强者可以封为 Teyrn，按照东南西北来划分，负责守卫国境，也可以召集旗下的诸侯，国王诞生于Teyrn中的强者，可以世袭，但是需要在贵族大会Landsmeet上获得支持，一旦不再强大之后就会被替换，类似坦格利安王朝之后的维斯特洛……

===================YY结束的分割线====================

其实这也可以说是一个逐级传递的致敬啦，应该很多人都知道《冰火》本身就是毫不隐晦的参考英伦的历史和地理：
灵感直接来自于英格兰的玫瑰战争（Wars of the Roses）。
北方的史塔克家族（House of Stark）和南方的兰尼斯特家族（House of Lannister），参考了以白玫瑰为纹章的约克家族（House of York）和以红玫瑰为纹章的兰开斯特家族（House of Lancaster）
从维斯特洛地图上那狭小的面积和形状就能看出，与其说它象征着欧洲次大陆，不如认为它就是大不列颠岛……
维斯特洛大陆上最早的人类种族——先民（the First Men），跟凯尔特人非常相似（包括旧神信仰，对自然的亲近，德鲁伊文化），就像凯尔特人，他们虽然被后来者当作“土著”，其实最开始也一样是入侵者，后来入侵的安达尔人类似盎格鲁人，安达尔人没能打下北境，盎格鲁人也让凯尔特人在苏格兰保留了势力。

===================联想结束的分割线====================

我认为能意识到Dragon Age: Origins就是冰与火之歌的PC GAME这一点是极其重要的！也许有一天你也会对《冰火》的电视剧和电影等的不耐烦，也许有一天我们会发现真正的演员名单距离理想中的标准相去甚远，也许有一天我们会更加确信：不提供好莱坞大片的巨额成本，再好的牌子也会做砸，也许有一天乔治马丁会把《冰火》写烂尾（呸，掌嘴），也许有一天你会认识到GreenRonin设计的冰火RPG同样不靠谱…………but it is not this day!…………咳咳对不起，不好意思，穿越了………………我想说的是……至少我们可以玩到这款Dragon Age: Origins！它不仅是由身为欧美RPG头牌的Bioware耗时多年设计开发，而且年初就会发售！而且是PC平台优先哑，同志们！……让我们在Ferelden相见……
对了，就算Dragon Age的设计师并非刻意的向《冰火》致敬，仅仅是“借鉴”和“启发”，而且不希望玩家把两者过度的关联（就像暴雪的设计师对DND的态度），然则我们还要注意到Bioware提供的Dragon Age toolset（游戏采用了新研发的RPG引擎Eclipse，所以NWN的toolset自然也该更新换代了），有了这种号称“我们开发Dragon Age本身也是用这套工具的呀”的SDK，相信冰火主题的MOD不会少……
另外我必须提醒的是：官方小说《Dragon Age: The Stolen Throne》也快出了，现在有章节预览，作者是绝对靠谱的David Gaider（DOA主设计师，《博德之门2》，《无冬之夜》，《星球大战：旧共和国骑士》的主设计师/编剧）
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2009/01/greywardens_wallpaper_thumb.gif' title='greywardens_wallpaper_thumb.gif'><img src='http://www.limboy.com/wp-content/uploads/2009/01/greywardens_wallpaper_thumb.gif' style="float:left;margin:0 10px 5px 0;" /></a>啊啊啊我现在对这部作品的热情超过辐射3了，Dragon Age: Origins的主旨是“回归原初（Origins）”，Bioware在战术和队友系统上确实是在回归博德之门，但是在剧情和设定方面，完全是在向乔治RR马丁那部被认为能以一抵四（四大名著）的<a target="_blank" href="http://www.douban.com/subject/1336330/">《冰与火之歌》</a>致敬哑！以下是《冰火》里的关键元素和对应的DAO设定：</p>
<h3>龙</h3>
<p>被认为已经灭绝的巨龙开始重新出现，还以此背景来给游戏命名</p>
<h3>异鬼</h3>
<p>难以理解的黑暗生物大军（Darkspawn）每隔几百年就大举入侵文明世界，被称作<a target="_blank" href="http://dragonage.bioware.com/theworld_history.html">the Blight</a>，而且同样跟远古异神（the Old Gods）有关，入侵方向好像也是由北向南？好像同样是从地下钻出来的？（有人认为《冰火》里的异鬼是野蛮人寻找冬之号角时从古代陵墓里挖出来的……）<span id="more-215"></span></p>
<h3>守夜人</h3>
<p>上古时代的第一次the Blight，无论在物质上还是心理上都造成了难以磨灭的巨大创伤，直接导致帝国毁灭，类似《冰火》的历史里记载的“长夜”，于是后人建立了特殊军事组织<a target="_blank" href="http://dragonage.bioware.com/greywardens.html">Grey Wardens</a>，战时作为与Darkspawn对抗的主力军，和平时期还要负责守护关于那些异界生物的知识，另外，他们跟《冰火》里的守夜人一样被现世的人们忽视，还拥有征募新兵的特权</p>
<h3>狼</h3>
<p>狼/狼人和狗在文化中有特殊地位（战犬还要占一个队友栏，有机会COS少狼主和Lord Snow了！大心！）</p>
<h3>学士</h3>
<p>在《冰火》里叫Maester，在DAO里叫Magi， Circle of Magi好像是类似学城的组织</p>
<h3>异域民族</h3>
<p>Ferelden跟《冰火》里的维斯特洛大陆（Westeros）一样，从世界观的角度来看是主要的大陆，从地理的角度来看只是很小的一块蛮荒之地。不过被遗忘国度里的Faerun在托瑞尔大陆的地位也差不多，西方人经历了数次“世界”的扩大，从地中海周边的罗马帝国，加入阿拉伯，加入远东，加入新大陆……可能形成了根深蒂固的“我们的世界观很狭隘，我们的大陆很蛮荒”的情结……</p>
<h3>瓦雷利亚帝国</h3>
<p>历史上曾经存在一统天下并且掌握强大魔法力量的Tevinter帝国，在灾变中覆灭，但是现今仍然在地理和文化上留下大量痕迹……（又是西方人的罗马帝国情结……）</p>
<h3>黑暗中世纪</h3>
<p>完全不像博得之门里那种已经接近蒸汽朋克的高魔世界（我认为超过了被遗忘国度原有的程度），而是类似维斯特洛大陆那种非常野蛮原始，非常现实主义的中世纪风格。官方自称黑暗奇幻（dark fantasy），而冰火正是dark complex epic fantasy</p>
<h3>封建领主和政治斗争</h3>
<p>Ferelden的基本权力单位是割据各地的小领主（被称作bann），占据重要城堡的贵族地位更高，称作arl，少数强者可以封为 Teyrn，按照东南西北来划分，负责守卫国境，也可以召集旗下的诸侯，国王诞生于Teyrn中的强者，可以世袭，但是需要在贵族大会Landsmeet上获得支持，一旦不再强大之后就会被替换，类似坦格利安王朝之后的维斯特洛……</p>
<p><br/><br />
===================YY结束的分割线====================<br />
<br/></p>
<p>其实这也可以说是一个逐级传递的致敬啦，应该很多人都知道《冰火》本身就是毫不隐晦的参考英伦的历史和地理：</p>
<p>灵感直接来自于英格兰的<a target="_blank" href="http://zh.wikipedia.org/wiki/%E7%8E%AB%E7%91%B0%E6%88%B0%E7%88%AD">玫瑰战争（Wars of the Roses）</a>。</p>
<p>北方的史塔克家族（House of Stark）和南方的兰尼斯特家族（House of Lannister），参考了以白玫瑰为纹章的约克家族（House of York）和以红玫瑰为纹章的兰开斯特家族（House of Lancaster）</p>
<p>从<a target="_blank" href="http://www.westeros.org/Citadel/Gallery/Entry/778/">维斯特洛地图</a>上那狭小的面积和形状就能看出，与其说它象征着欧洲次大陆，不如认为它就是大不列颠岛……</p>
<p>维斯特洛大陆上最早的人类种族——先民（the First Men），跟凯尔特人非常相似（包括旧神信仰，对自然的亲近，德鲁伊文化），就像凯尔特人，他们虽然被后来者当作“土著”，其实最开始也一样是入侵者，后来入侵的安达尔人类似盎格鲁人，安达尔人没能打下北境，盎格鲁人也让凯尔特人在苏格兰保留了势力。</p>
<p><br/><br />
===================联想结束的分割线====================<br />
<br/></p>
<p>我认为能意识到Dragon Age: Origins就是冰与火之歌的PC GAME这一点是极其重要的！也许有一天你也会对《冰火》的电视剧和电影等的不耐烦，也许有一天我们会发现真正的演员名单距离<a target="_blank" href="http://winter-is-coming.blogspot.com/2009/01/westeros-forum-chooses-cast.html">理想中的标准</a>相去甚远，也许有一天我们会更加确信：不提供好莱坞大片的巨额成本，再好的牌子也会做砸，也许有一天乔治马丁会把《冰火》写烂尾（呸，掌嘴），也许有一天你会认识到GreenRonin设计的<a href="http://www.greenronin.com/sifrp/">冰火RPG</a>同样不靠谱…………but it is not this day!…………咳咳对不起，不好意思，穿越了………………我想说的是……至少我们可以玩到这款Dragon Age: Origins！它不仅是由身为欧美RPG头牌的Bioware耗时多年设计开发，而且年初就会发售！而且是PC平台优先哑，同志们！……让我们在Ferelden相见……</p>
<p>对了，就算Dragon Age的设计师并非刻意的向《冰火》致敬，仅仅是“借鉴”和“启发”，而且不希望玩家把两者过度的关联（就像暴雪的设计师对DND的态度），然则我们还要注意到Bioware提供的<a target="_blank" href="http://dragonage.bioware.com/gallery_worldbuilders.html">Dragon Age toolset</a>（游戏采用了新研发的RPG引擎Eclipse，所以NWN的toolset自然也该更新换代了），有了这种号称“我们开发Dragon Age本身也是用这套工具的呀”的SDK，相信冰火主题的MOD不会少……</p>
<p>另外我必须提醒的是：官方小说《Dragon Age: The Stolen Throne》也快出了，现在有<a target="_blank"  href="http://dragonage.bioware.com/noveltst.html">章节预览</a>，作者是绝对靠谱的<a target="_blank" href="http://www.mobygames.com/developer/sheet/view/developerId,46665/">David Gaider</a>（DOA主设计师，《博德之门2》，《无冬之夜》，《星球大战：旧共和国骑士》的主设计师/编剧）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2009/01/20/dragon_age_is_the_song_of_ice_and_fire/feed/</wfw:commentRss>
		<slash:comments>2</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>徐家汇战记</title>
		<link>http://www.limboy.com/2008/12/28/cerebellum/</link>
		<comments>http://www.limboy.com/2008/12/28/cerebellum/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 13:21:21 +0000</pubDate>
		<dc:creator>Dexter.Yy</dc:creator>
				<category><![CDATA[纯水]]></category>

		<guid isPermaLink="false">http://www.limboy.com/2008/12/28/cerebellum/</guid>
		<description><![CDATA[今天星巴克人满为患找不到地方看书，我便去bestbuy给新ipod买硅胶套子，在地铁站入口处感觉耳机线被扯到了，回头在4点钟方向隐约看到白色的线和半个身体，再摸右边口袋，意识到里面什么都没有，立刻吓呆了，脑子里蹦出一大串想法，但其中最大最醒目最闪耀的是：啥时候买新的？
我以前在头脑里推演过这种事件，但是没想到现实中一切都发生的这么快，4点方向已经没有人影，在拥挤的人群中追上小偷大概也只有好莱坞动作片主角才能做到，所以我只是发呆，不知道下一步该做什么，而身体却在下意识的行动，不知不觉已经转到10点钟方向，几步远前方有一个穿黑衣的走过，被我一把抓住
这个人说他没拿，我当时继续发呆，心想我能怎么办，我有啥办法知道他拿了还是没拿……我居然没反应过来一个人被陌生人抓到衣服之后第一句话不该说我没拿！但是身体仍然在行动，手没松开，还把他拉到路边。我还在想其他事，没听见他又说了什么，他却突然把ipod还给我了，想来是被我的表情骇到了
于是我的ipod奇迹般的失而复得，这是何等荣耀的胜利！荣耀不属于大脑，它在这次事件中无所作为，完全沉浸在“刚才本来应该……”，“损失多大”，“还能做什么”之类的想法里。在紧要关头，是小脑挺身而出！告诉我们这种情况下最重要的只有三件事：1，行动。2，行动。3，行动。
伟大的小脑同志甚至还帮助我摆出了很横很能打的表情，迫使对方放弃了逃跑和还击的念头——其实很容易办到，我背着很重的macbook pro和head first设计模式，一定打不过也追不过。
Gloria in Excelsis Cerebellum!
前几天刚看过一篇文章说“无意识的大脑才能做出最佳决定”，我今天的实践成为了绝佳的佐证！喔，这还让我想到了一个叫超然会(Transcendant Order)的组织……
P.S. 以上文字本来准备发在twitter上的，因此可以看到前几段话都严格限制为140个字符，我觉得用这种方式写东西很有效率，如果直接在wordpress里写，字数一定会翻几倍……
]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.limboy.com/wp-content/uploads/2008/12/cerebellum.jpg' title='cerebellum.jpg'><img src='http://www.limboy.com/wp-content/uploads/2008/12/cerebellum.jpg' alt='cerebellum.jpg' style="width:200px;float:left;margin:0;border:0;" /></a>今天星巴克人满为患找不到地方看书，我便去bestbuy给新ipod买硅胶套子，在地铁站入口处感觉耳机线被扯到了，回头在4点钟方向隐约看到白色的线和半个身体，再摸右边口袋，意识到里面什么都没有，立刻吓呆了，脑子里蹦出一大串想法，但其中最大最醒目最闪耀的是：啥时候买新的？</p>
<p>我以前在头脑里推演过这种事件，但是没想到现实中一切都发生的这么快，4点方向已经没有人影，在拥挤的人群中追上小偷大概也只有好莱坞动作片主角才能做到，所以我只是发呆，不知道下一步该做什么，而身体却在下意识的行动，不知不觉已经转到10点钟方向，几步远前方有一个穿黑衣的走过，被我一把抓住</p>
<p>这个人说他没拿，我当时继续发呆，心想我能怎么办，我有啥办法知道他拿了还是没拿……我居然没反应过来一个人被陌生人抓到衣服之后第一句话不该说我没拿！但是身体仍然在行动，手没松开，还把他拉到路边。我还在想其他事，没听见他又说了什么，他却突然把ipod还给我了，想来是被我的表情骇到了<span id="more-206"></span></p>
<p>于是我的ipod奇迹般的失而复得，这是何等荣耀的胜利！荣耀不属于大脑，它在这次事件中无所作为，完全沉浸在“刚才本来应该……”，“损失多大”，“还能做什么”之类的想法里。在紧要关头，是小脑挺身而出！告诉我们这种情况下最重要的只有三件事：1，行动。2，行动。3，行动。</p>
<p>伟大的小脑同志甚至还帮助我摆出了很横很能打的表情，迫使对方放弃了逃跑和还击的念头——其实很容易办到，我背着很重的macbook pro和head first设计模式，一定打不过也追不过。</p>
<p>Gloria in Excelsis Cerebellum!</p>
<p>前几天刚看过一篇文章说“<a href="http://www.yeeyan.com/articles/view/jiaokai/20592" target="_blank">无意识的大脑才能做出最佳决定</a>”，我今天的实践成为了绝佳的佐证！喔，这还让我想到了一个叫<a href="http://www.ntrpg.org/yy/undertopia/article.php?articleid=636&#038;pagenum=14" target="_blank">超然会(Transcendant Order)</a>的组织……</p>
<p>P.S. 以上文字本来准备发在<a href="http://twitter.com/dexteryy" target="_blank">twitter</a>上的，因此可以看到前几段话都严格限制为140个字符，我觉得用这种方式写东西很有效率，如果直接在wordpress里写，字数一定会翻几倍……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limboy.com/2008/12/28/cerebellum/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<t
