<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[X-Intend]]></title>
<link><![CDATA[http://www.xintend.com/]]></link>
<description><![CDATA[超级打算---每个人都有自己的IDEA]]></description>
<language><![CDATA[]]></language>
<copyright><![CDATA[Copyright X-Intend]]></copyright>
<webMaster><![CDATA[oicuicu@gmail.com]]></webMaster>
<generator><![CDATA[Roclog v5.0.2]]></generator>
<image>
	<title><![CDATA[X-Intend]]></title>
	<url><![CDATA[http://www.xintend.com/Common/Images/Logo.png]]></url>
	<link><![CDATA[http://www.xintend.com/]]></link>
	<description><![CDATA[超级打算---每个人都有自己的IDEA]]></description>
</image>
<item>
	<link><![CDATA[http://www.xintend.com/article/blog_upgrade_to_5.0.aspx]]></link>
	<title><![CDATA[辛苦的升级]]></title>
	<author><![CDATA[kingfo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-7-24 12:44:27</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/blog_upgrade_to_5.0.aspx]]></guid>
	<description><![CDATA[<p>从3.2.15 逐步升级到 5.0.0 真受痛苦，之后的版本由于本人愚钝。。。还是无法升级至最新的isroc。。。。<img alt="" src="http://www.xintend.com/Common/Editor/FCKeditor/editor/images/smiley/cry_smile.gif" /></p>
<p>&nbsp;</p>
<p>话说最新的编辑器让我非常郁闷。。。缺少了代码的所见即所得的部分。。。。<img alt="" src="http://www.xintend.com/Common/Editor/FCKeditor/editor/images/smiley/sad_smile.gif" /></p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/timeing_as3.aspx]]></link>
	<title><![CDATA[周期]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-6-23 22:24:53</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/timeing_as3.aspx]]></guid>
	<description><![CDATA[<p>本周最值得关注的blog：</p>
<p>http://blog.kaourantin.net/ &nbsp;之&nbsp;http://www.kaourantin.net/2010/03/timing-it-right.html 及&nbsp;http://blog.kaourantin.net/?p=83</p>
<p>受影响的 API和类：</p>
<p>EI &nbsp; LC &nbsp;Timer &nbsp;EnterFrame &nbsp; throw 等</p>
<p>新的Trine计划有待测试</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/XcpXzVjuDgUqJuUCcnfU.aspx]]></link>
	<title><![CDATA[生成随机字符串的密封类]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-5-11 11:35:11</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/XcpXzVjuDgUqJuUCcnfU.aspx]]></guid>
	<description><![CDATA[<p>C# 代码&nbsp;</p>
<p>&nbsp;</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">using</span><span>&nbsp;&nbsp;&nbsp;System;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">using</span><span>&nbsp;&nbsp;&nbsp;System.Security.Cryptography;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">namespace</span><span>&nbsp;&nbsp;&nbsp;YNIT.Components&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;生成随机字符串的密封类，不能被继承&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;/summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">sealed</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">class</span><span>&nbsp;&nbsp;&nbsp;RandomStr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">readonly</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;defaultLength&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;8;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;GetNewSeed()&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">byte</span><span>[]&nbsp;&nbsp;&nbsp;rndBytes&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;</span><span class="keyword">new</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[4];&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;RNGCryptoServiceProvider&nbsp;&nbsp;&nbsp;rng&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>&nbsp;&nbsp;&nbsp;RNGCryptoServiceProvider();&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;rng.GetBytes(rndBytes);&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;BitConverter.ToInt32(rndBytes,0);&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeAll(</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;strLen)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;System.Random&nbsp;&nbsp;&nbsp;RandomObj&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>&nbsp;&nbsp;&nbsp;System.Random(GetNewSeed());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;buildRndCodeReturn&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;</span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;i=0;&nbsp;&nbsp;&nbsp;i&lt;strLen;&nbsp;&nbsp;&nbsp;i++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;buildRndCodeReturn&nbsp;&nbsp;&nbsp;+=&nbsp;&nbsp;&nbsp;(<span class="keyword">char</span><span>)RandomObj.Next(33,125);&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;buildRndCodeReturn;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span><span class="preprocessor">&nbsp;&nbsp;&nbsp;</span>&nbsp;</span></li><li><span><span class="preprocessor">&nbsp;&nbsp;#region&nbsp;&nbsp;&nbsp;输出随机字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;输出长度为8的随机字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;/summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;returns&gt;长度为8的随机字符串&lt;/returns&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;GetRndStrOfAll()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeAll(defaultLength);&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;输出指定长度的随机字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;/summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;param&nbsp;&nbsp;&nbsp;name=&quot;LenOf&quot;&gt;长度&lt;/param&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;returns&gt;指定长度的随机字符串&lt;/returns&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;GetRndStrOfAll(</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;LenOf)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeAll(LenOf);&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span><span class="preprocessor">&nbsp;&nbsp;#endregion&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;sCharLow&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;</span><span class="string">&quot;abcdefghijklmnopqrstuvwxyz&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;sCharUpp&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;</span><span class="string">&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;sNumber&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;</span><span class="string">&quot;0123456789&quot;</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeOnly(</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;StrOf,</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;strLen)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;System.Random&nbsp;&nbsp;&nbsp;RandomObj&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;<span class="keyword">new</span><span>&nbsp;&nbsp;&nbsp;System.Random(GetNewSeed());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;buildRndCodeReturn&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;</span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;i=0;&nbsp;&nbsp;&nbsp;i&lt;strLen;&nbsp;&nbsp;&nbsp;i++)&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;buildRndCodeReturn&nbsp;&nbsp;&nbsp;+=&nbsp;&nbsp;&nbsp;StrOf.Substring(RandomObj.Next(0,StrOf.Length-1),1);&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;buildRndCodeReturn;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span><span class="preprocessor">&nbsp;&nbsp;&nbsp;</span>&nbsp;</span></li><li><span><span class="preprocessor">&nbsp;&nbsp;#region&nbsp;&nbsp;&nbsp;输出指定范围随机字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;输出长度为8的小写字母加数字的字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;/summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;returns&gt;长度为8的小写字母加数字的字符串&lt;/returns&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;GetRndStrOnlyFor()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeOnly(sCharLow&nbsp;&nbsp;&nbsp;+&nbsp;&nbsp;&nbsp;sNumber,defaultLength);&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;输出指定长度的小写字母加数字的字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;/summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;param&nbsp;&nbsp;&nbsp;name=&quot;LenOf&quot;&gt;长度&lt;/param&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;returns&gt;指定长度的小写字母加数字的字符串&lt;/returns&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;GetRndStrOnlyFor(</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;LenOf)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeOnly(sCharLow&nbsp;&nbsp;&nbsp;+&nbsp;&nbsp;&nbsp;sNumber,LenOf);&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;输出长度为8的指定字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;/summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;param&nbsp;&nbsp;&nbsp;name=&quot;bUseUpper&quot;&gt;是否含有大写字母&lt;/param&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;param&nbsp;&nbsp;&nbsp;name=&quot;bUseNumber&quot;&gt;是否含有数字&lt;/param&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;returns&gt;长度为8的指定字符串&lt;/returns&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;GetRndStrOnlyFor(</span><span class="keyword">bool</span><span>&nbsp;&nbsp;&nbsp;bUseUpper,</span><span class="keyword">bool</span><span>&nbsp;&nbsp;&nbsp;bUseNumber)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;strTmp&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;sCharLow;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;&nbsp;&nbsp;(bUseUpper)&nbsp;&nbsp;&nbsp;strTmp&nbsp;&nbsp;&nbsp;+=&nbsp;&nbsp;&nbsp;sCharUpp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;&nbsp;&nbsp;(bUseNumber)&nbsp;&nbsp;&nbsp;strTmp&nbsp;&nbsp;&nbsp;+=&nbsp;&nbsp;&nbsp;sNumber;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeOnly(strTmp,defaultLength);&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;输出指定长度的指定字符串&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;/summary&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;param&nbsp;&nbsp;&nbsp;name=&quot;LenOf&quot;&gt;长度&lt;/param&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;param&nbsp;&nbsp;&nbsp;name=&quot;bUseUpper&quot;&gt;是否含有大写字母&lt;/param&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;param&nbsp;&nbsp;&nbsp;name=&quot;bUseNumber&quot;&gt;是否含有数字&lt;/param&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">///&nbsp;&nbsp;&nbsp;&lt;returns&gt;指定长度的指定字符串&lt;/returns&gt;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">static</span><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;GetRndStrOnlyFor(</span><span class="keyword">int</span><span>&nbsp;&nbsp;&nbsp;LenOf,</span><span class="keyword">bool</span><span>&nbsp;&nbsp;&nbsp;bUseUpper,</span><span class="keyword">bool</span><span>&nbsp;&nbsp;&nbsp;bUseNumber)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">string</span><span>&nbsp;&nbsp;&nbsp;strTmp&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;sCharLow;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;&nbsp;&nbsp;(bUseUpper)&nbsp;&nbsp;&nbsp;strTmp&nbsp;&nbsp;&nbsp;+=&nbsp;&nbsp;&nbsp;sCharUpp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;&nbsp;&nbsp;(bUseNumber)&nbsp;&nbsp;&nbsp;strTmp&nbsp;&nbsp;&nbsp;+=&nbsp;&nbsp;&nbsp;sNumber;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;&nbsp;&nbsp;BuildRndCodeOnly(strTmp,LenOf);&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</span></li><li><span><span class="preprocessor">&nbsp;&nbsp;#endregion&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;</span></li></ol></pre>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/how_to_control_input_height.aspx]]></link>
	<title><![CDATA[[不得不转]如何更好地控制input输入框的高度]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-5-11 10:24:29</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/how_to_control_input_height.aspx]]></guid>
	<description><![CDATA[<p>按：看到如此细致的文章，真的很爱~~ 转载如此。向作者致敬~！&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="post-301 post hentry category-htmlandcss category-front-end" id="post-301">
<h2 class="title">如何更好地控制input输入框的高度</h2>
<div class="info"><img alt="" src="http://www.gravatar.com/avatar/264e8ddaac0e88629011935bf857cd4d?s=32&amp;d=http%3A%2F%2Fwww.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&amp;r=G" class="avatar avatar-32 photo" height="32" width="32" /><span class="author">作者：<a href="http://www.baiduux.com/blog/author/nwind/" title="由 nwind 发表">nwind</a></span><span class="date">类别：<a href="http://www.baiduux.com/blog/category/front-end/html_and_css/" title="查看 HTML/CSS 的全部文章" rel="category tag">HTML/CSS</a>,  <a href="http://www.baiduux.com/blog/category/front-end/" title="查看 前端技术
的全部文章" rel="category tag">前端技术</a> |   <a href="http://www.baiduux.com/blog/2010/05/05/how_to_control_input_height/#comments" title="如何更好地控制input输入框的高度 上的评论">评论(3)</a></span></div>
<p>很久以前Roger Johansson就在他的blog上做了一个用样式控制表单元素的测试,  告诉我们企图用样式控制表单元素是一件不可能的事情</p>
<blockquote>
<p>using CSS to style form controls to look exactly the same  across browsers and platforms is impossible</p>
</blockquote>
<p>甚至css2.1规范中也没有明确这方面的规定, 而是打算将它fix in future</p>
<blockquote>
<p>CSS 2.1 does not define which properties apply to form  controls and frames, or how CSS can be used to style them. User agents  may apply CSS properties to these elements. Authors are recommended to  treat such support as experimental. A future level of CSS may specify  this further.</p>
</blockquote>
<p>所以如果想要让表单元素在各个浏览器下完全一致, 最好的解决方法莫过于完全不理会操作系统的样式, 用自定义的ui风格,  就像bing或Google的Jazz UI那样</p>
<p><img src="http://imgsrc.baidu.com/forum/mpic/item/7b8dc4fbd678f1e4b58f3164.jpg" alt="" /></p>
<p>然而, 这会导致界面和用户的系统格格不入, 目前google主要还是针对浏览器做了些特殊处理,  如webkit下用gradient使得按钮看上去好些</p>
<p><img src="http://imgsrc.baidu.com/forum/mpic/item/5214b555e9c7f2253b293564.jpg" alt="" /></p>
<p>mac下webkit的按钮不好控制</p>
<p><img src="http://imgsrc.baidu.com/forum/mpic/item/0665a0243f185e5a35a80f64.jpg" alt="" /></p>
<p>本文将就输入框高度的问题进行调研, 寻找更好的解决方法</p>
<p>&nbsp;</p>
<h2><b>输入框高度</b></h2>
<p>首先, 这个调研的一个主要原因是, 搜索结果页打算进入标准模式, 这会导致盒模型的变化, 造成输入框高度和原来不一样,  所以为了和线上效果保持一致, 我们需要找到一个最佳的解决方案</p>
<p>有同学可能会不解, 有那么难么? 设置一个height不就解决了么?</p>
<pre><div class="codecolorer-container html4strict default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="html4strict codecolorer" style="white-space: nowrap;"><span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text&quot;</span> <span class="kw3">style</span><span class="sy0">=</span><span class="st0">&quot;height:28px&quot;</span> <span class="sy0">/</span>&gt;</span></div></div>
</pre>
<p>然而, 经测试发现这里面的细节问题还是还挺多, 由于资源有限, 这里只测试了主要的浏览器和平台, 包括目前主要用到的5个浏览器</p>
<ul>
    <li>IE6(xp)</li>
    <li>IE7(xp)</li>
    <li>IE8(win7)</li>
    <li>Firefox 3.5(xp)</li>
    <li>Firefox 3.5(win7)</li>
    <li>Firefox 3.5(mac 10.6.2)</li>
    <li>Firefox 3.5(ubuntu 10.4)</li>
    <li>Chrome 5(xp)</li>
    <li>Chrome 5(win7)</li>
    <li>Chrome 5(mac 10.6.2)</li>
    <li>Chrome 5(ubuntu 10.4)</li>
</ul>
<h3><b>通过设定height的方式</b></h3>
<p>我们的目标是和目前搜索框大小保持一致, 既28px</p>
<p>首先测试的是最简单的height, 先看目前线上的方案(简单起见就直接写到style中了)</p>
<pre><div class="codecolorer-container html4strict default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="html4strict codecolorer" style="white-space: nowrap;"><span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text&quot;</span> <span class="kw3">style</span><span class="sy0">=</span><span class="st0">&quot;font: 16px arial; height: 1.78em; padding-top:2px&quot;</span> <span class="sy0">/</span>&gt;</span></div></div>
</pre>
<p>从样式上推导, 由于盒模型问题, 在IE下的大小将是1.78 * 16 = 28px, 而Firefox等浏览器应该是1.78 * 16 +  2px + border-width * 2 = 30 + ? px</p>
<p>测试结果是</p>
<table>
    <tbody>
        <tr>
            <th>浏览器</th>
            <th>height + padding-top + padding-bottom + border-top-width +  border-bottom-width</th>
        </tr>
        <tr>
            <td>IE6(xp)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>IE7(xp)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>IE8(win7)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>Firefox 3.5(xp)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>Firefox 3.5(win7)</td>
            <td>23 + 2 + 1 + 1 + 1 = 28</td>
        </tr>
        <tr>
            <td>Firefox 3.5(mac 10.6.2)</td>
            <td>19 + 2 + 1 + 3 + 3 = 28</td>
        </tr>
        <tr>
            <td>Firefox 3.5(ubuntu 10.04)</td>
            <td>19 + 2 + 1 + 3 + 3 = 28</td>
        </tr>
        <tr>
            <td>Chrome 5(xp)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>Chrome 5(win7)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>Chrome 5(mac 10.6.2)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>Chrome 5(ubuntu 10.04)</td>
            <td>21 + 2 + 1 + 2 + 2 = 28</td>
        </tr>
    </tbody>
</table>
<p>效果相当理想, 所有浏览器都是28px, 看来即使是Firefox和Chrom在quirks模式下的input都没有遵循盒模型,  所以线上的输入框高度在各个浏览器下很完美地保持一致</p>
<p>然而如果是在standards模式下, 结果则是</p>
<table>
    <tbody>
        <tr>
            <th>浏览器</th>
            <th>height + padding-top + padding-bottom + border-top-width +  border-bottom-width</th>
        </tr>
        <tr>
            <td>IE6(xp)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
        <tr>
            <td>IE7(xp)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
        <tr>
            <td>IE8(win7)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
        <tr>
            <td>Firefox 3.5(xp)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
        <tr>
            <td>Firefox 3.5(win7)</td>
            <td>28 + 2 + 1 + 1 + 1 = 32</td>
        </tr>
        <tr>
            <td>Firefox 3.5(mac 10.6.2)</td>
            <td>28 + 2 + 1 + 3 + 3 = 37</td>
        </tr>
        <tr>
            <td>Firefox 3.5(ubuntu 10.04)</td>
            <td>28 + 2 + 1 + 3 + 3 = 37</td>
        </tr>
        <tr>
            <td>Chrome 5(xp)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
        <tr>
            <td>Chrome 5(win7)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
        <tr>
            <td>Chrome 5(mac 10.6.2)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
        <tr>
            <td>Chrome 5(ubuntu 10.04)</td>
            <td>28 + 2 + 1 + 2 + 2 = 35</td>
        </tr>
    </tbody>
</table>
<p>就仅仅加了一句</p>
<div class="codecolorer-container text default" style="overflow: auto;
white-space: nowrap; width: auto;">
<div class="text codecolorer" style="white-space: nowrap;">&lt;!DOCTYPE html&gt;</div>
</div>
<p>, 却导致浏览器差距变得如此大, 仔细观察发现, 主要问题在Firefox上 它的border在win7下是1像素, xp下是2像素,  mac下是3像素, 令人很头疼, 于是打算换一种方案试试</p>
<h3><b>padding的方式</b></h3>
<p>由于Firefox的border问题, 设定height是不可能保证高度一致的, 除非判断再去判断操作系统类型, 但那样做太麻烦了,  而且说不定mobile版又不一样</p>
<p>那是否可以不通过设置height来控制? 在目前的大搜索首页也是standards模式,  它是采用padding的方式来实现28px的高度的</p>
<pre><div class="codecolorer-container html4strict default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="html4strict codecolorer" style="white-space: nowrap;"><span class="sc2">&lt;<a href="http://december.com/html/4/element/input.html"><span class="kw2">input</span></a> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text&quot;</span> <span class="kw3">style</span><span class="sy0">=</span><span class="st0">&quot;font: 16px arial; padding:3px&quot;</span> <span class="sy0">/</span>&gt;</span></div></div>
</pre>
<p>这种写法的测试结果是</p>
<table>
    <tbody>
        <tr>
            <th>浏览器</th>
            <td>height + padding-top + padding-bottom + border-top-width +  border-bottom-width</td>
        </tr>
        <tr>
            <td>IE6(xp)</td>
            <td>18 + 3 + 3 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>IE7(xp)</td>
            <td>18 + 3 + 3 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>IE8(win7)</td>
            <td>18 + 3 + 3 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>Firefox 3.5(xp)</td>
            <td>19 + 3 + 3 + 2 + 2 = 29</td>
        </tr>
        <tr>
            <td>Firefox 3.5(win7)</td>
            <td>19 + 3 + 3 + 1 + 1 = 27</td>
        </tr>
        <tr>
            <td>Firefox 3.5(mac 10.6.2)</td>
            <td>20 + 3 + 3 + 3 + 3 = 32</td>
        </tr>
        <tr>
            <td>Firefox 3.5(ubuntu 10.04)</td>
            <td>19 + 3 + 3 + 3 + 3 = 31</td>
        </tr>
        <tr>
            <td>Chrome 5(xp)</td>
            <td>19 + 3 + 3 + 2 + 2 = 29</td>
        </tr>
        <tr>
            <td>Chrome 5(win7)</td>
            <td>19 + 3 + 3 + 2 + 2 = 29</td>
        </tr>
        <tr>
            <td>Chrome 5(mac 10.6.2)</td>
            <td>18 + 3 + 3 + 2 + 2 = 28</td>
        </tr>
        <tr>
            <td>Chrome 5(ubuntu 10.04)</td>
            <td>19 + 3 + 3 + 2 + 2 = 29</td>
        </tr>
    </tbody>
</table>
<p>在不设定输入框高度的情况下, 浏览器会自行指定一个, 而且都有差距, mac上的Firefox更是高出了4像素, 但总的来说,  效果虽然不完美, 但还是可以接受, 大部分情况下都只差一个像素</p>
<p>然而这种方法带来了很多不确定性, 内容区的高度是随着字体大小而变的, 假设font-size是14px, 浏览器的高度又保持一致了</p>
<table>
    <tbody>
        <tr>
            <th>浏览器</th>
            <th>height</th>
        </tr>
        <tr>
            <td>IE6(xp)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>IE7(xp)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>IE8(win7)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Firefox 3.5(xp)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Firefox 3.5(win7)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Firefox 3.5(mac 10.6.2)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Firefox 3.5(ubuntu 10.04)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Chrome 5(xp)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Chrome 5(win7)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Chrome 5(mac 10.6.2)</td>
            <td>16</td>
        </tr>
        <tr>
            <td>Chrome 5(ubuntu 10.04)</td>
            <td>16</td>
        </tr>
    </tbody>
</table>
<p>是否还有更好的方案呢?</p>
<h3><b>box-sizing</b></h3>
<p>height和padding都无法完美控制输入框高度, 而border的大小又不能改, 难道就真的没办法了么?  不禁怀念quirks模式下的方便, 设定一个高度就完美了, 要是能既进standards模式, 又能用到旧盒模型就好了,  很自然地就想到了一个从来没用过的css属性box-sizing, 以前一直没想好这属性到底能用在哪里, 终于这下派上用场了,  使用它我们就可以解决Firefox下3种border的区别, 让Firefox自己去算内容区的高度</p>
<p>然而由于IE6/7不支持这个属性, 所以需要写hack, 由于IE下的默认border值是2, padding是1,  所以height需要减6像素, 也就是</p>
<pre><div class="codecolorer-container css default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="css codecolorer" style="white-space: nowrap;">-moz-box-sizing<span class="sy0">:</span> border-box<span class="sy0">;</span><br /> -webkit-box-sizing<span class="sy0">:</span> border-box<span class="sy0">;</span><br /> box-sizing<span class="sy0">:</span> border-box<span class="sy0">;</span><br /> <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">28px</span><span class="sy0">;</span><br /> <span class="sy0">*</span><span class="kw1">height</span><span class="sy0">:</span> <span class="re3">22px</span><span class="sy0">;</span></div></div>
</pre>
<p>这样, 就能保证绝大部分的浏览器下效果一致了, box-sizing属性的支持情况如下表所示, 来自mozilla, 支持的访问非常广</p>
<table>
    <tbody>
        <tr>
            <th>Browser</th>
            <th>Lowest Version</th>
            <th>Support of</th>
        </tr>
        <tr>
            <td>Internet Explorer</td>
            <td>8.0</td>
            <td>box-sizing</td>
        </tr>
        <tr>
            <td>Firefox (Gecko)</td>
            <td>1.0 (1.0)</td>
            <td>-moz-box-sizing</td>
        </tr>
        <tr>
            <td>Opera</td>
            <td>7.0</td>
            <td>box-sizing</td>
        </tr>
        <tr>
            <td>Safari (WebKit)</td>
            <td>3.0 (522)</td>
            <td>-webkit-box-sizing</td>
        </tr>
    </tbody>
</table>
<p>不过, 事情还没有结束, 刚才假定了IE下默认padding是1像素, 然而目前很多css  reset都会将input的padding设为0, 于是, IE下的差别将不是6像素, 而是4像素, 所以为了避免受到影响,  建议将padding设为0</p>
<pre><div class="codecolorer-container css default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="css codecolorer" style="white-space: nowrap;"><span class="kw1">padding-top</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br /> <span class="kw1">padding-bottom</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br /> <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">28px</span><span class="sy0">;</span><br /> <span class="sy0">*</span><span class="kw1">height</span><span class="sy0">:</span> <span class="re3">24px</span><span class="sy0">;</span></div></div>
</pre>
<h3><b>浏览器在quirks下的实现方法</b></h3>
<p>回过头来看Firefox和Chrome在quirks模式下使用了非标准的盒模型, 看样子是有意去做的, 它是如何实现的呢?</p>
<p>于是在webkit源码中寻找, 一开始以为它是在源码中对quirks下的input做了特殊处理, 但没看找到又什么特别的地方,  而在看到计算box高度的时候</p>
<pre><div class="codecolorer-container c default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="c codecolorer" style="white-space: nowrap;"><span class="kw4">int</span> RenderBox<span class="sy0">::</span><span class="me2">calcContentBoxHeight</span><span class="br0">(</span><span class="kw4">int</span> height<span class="br0">)</span> <span class="kw4">const</span><br /> <span class="br0">{</span><br /> &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">(</span>style<span class="br0">(</span><span class="br0">)</span><span class="sy0">-&gt;</span>boxSizing<span class="br0">(</span><span class="br0">)</span> <span class="sy0">==</span> BORDER_BOX<span class="br0">)</span><br /> &nbsp; &nbsp; &nbsp; &nbsp; height <span class="sy0">-=</span> <span class="br0">(</span>borderTop<span class="br0">(</span><span class="br0">)</span> <span class="sy0">+</span> borderBottom<span class="br0">(</span><span class="br0">)</span> <span class="sy0">+</span> paddingTop<span class="br0">(</span><span class="br0">)</span> <span class="sy0">+</span> paddingBottom<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="sy0">;</span><br /> &nbsp; &nbsp; <span class="kw1">return</span> max<span class="br0">(</span>0<span class="sy0">,</span> height<span class="br0">)</span><span class="sy0">;</span><br /> <span class="br0">}</span></div></div>
</pre>
<p>忽然想到, 会不会是通过浏览器默认样式来实现的呢? 将这种特殊的逻辑直接写在代码中确实太恶心了, 既然支持box-sizing属性,  直接将它写在quirks的默认样式不就完美解决了么</p>
<p>果然, 在Firefox的res/quirk.css中发现了这句</p>
<pre><div class="codecolorer-container css default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="css codecolorer" style="white-space: nowrap;"><span class="coMULTI">/*<br /> * Quirk: Use border-box box sizing for text inputs, password inputs, and<br /> * textareas. &nbsp;(b=184478 on why we use content-box sizing in standards mode)<br /> */</span><br /> <br /> <span class="coMULTI">/* Note that all other<br /> &lt;input&gt;s already use border-box<br /> sizing, so we're ok with this selector */</span><br /> input<span class="sy0">:</span>not<span class="br0">(</span><span class="br0">[</span>type<span class="sy0">=</span>image<span class="br0">]</span><span class="br0">)</span><span class="sy0">,</span> textarea <span class="br0">{</span><br /> &nbsp; -moz-box-sizing<span class="sy0">:</span> border-box<span class="sy0">;</span><br /> <span class="br0">}</span></div></div>
</pre>
<p>在webkit源码中的WebCore/css/quirks.css发现了这句</p>
<pre><div class="codecolorer-container css default" style="overflow: auto; white-space: nowrap; width: auto;"><div class="css codecolorer" style="white-space: nowrap;"><span class="coMULTI">/* This will apply only to text fields, since all other inputs already use border box sizing */</span><br /> input<span class="sy0">:</span>not<span class="br0">(</span><span class="br0">[</span>type<span class="sy0">=</span>image<span class="br0">]</span><span class="br0">)</span><span class="sy0">,</span> textarea <span class="br0">{</span><br /> &nbsp; &nbsp; -webkit-box-sizing<span class="sy0">:</span> border-box<span class="sy0">;</span><br /> <span class="br0">}</span></div></div>
</pre>
<p>原来浏览器就是这么解决的, 那么在标准模式下用它将是一种比较好的方案</p>
<h3><b>one more thing</b></h3>
<p>不过这种写法在Firefox 3.5以下的版本会有个问题, 那就是输入框内容将无法垂直居中, 以英文为例, 3.5中和顶部的差距是5像素,  而3.6是7像素, 目前还没想到解决方案</p>
<p><img src="http://imgsrc.baidu.com/forum/mpic/item/d23367de0a98c92948540364.jpg" alt="" /></p>
<p>幸好在Firefox 3.6中解决了这个问题, 而且3.5会默认升级到3.6, 所以这个问题也就不需要考虑了</p>
<h2><b>结论</b></h2>
<p>从这个例子可以痛苦地体验, 如果没有统一的规范, 要兼容不同浏览器是如此的困难, 而且这还仅仅是一个很不完全的测试,  好在浏览器还是尽可能做到了最大兼容, 比如, 假设windows下默认主题和经典主题有区别, 就意味着所有windows下的测试都要乘2</p>
</div>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/hg_mercurial_intro.aspx]]></link>
	<title><![CDATA[[转载]HG:Mercurial - 分布式版本控制系统]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-4-30 10:16:35</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/hg_mercurial_intro.aspx]]></guid>
	<description><![CDATA[<p>&nbsp;</p>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">1、下载地址：<a style="color: rgb(17, 17, 0); text-decoration: underline; " href="http://www.selenic.com/mercurial/wiki/index.cgi/Mercurial"><font color="#5c81a7">Mercurial 主页</font></a>，安装时一定要同意其自启动。</div>
<ul>
    <li style="list-style-type: none; list-style-position: initial; list-style-image: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">有关多种版本控制软件的优劣势，请参看<a style="color: rgb(17, 17, 0); text-decoration: underline; " href="http://en.wikipedia.org/wiki/Comparison_of_revision_control_software"><font color="#5c81a7">多种版本控制软件的比较</font></a>。</li>
    <li style="list-style-type: none; list-style-position: initial; list-style-image: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">深入了解 Distributed Revision Control with Mercurial， 请参考<a style="color: rgb(17, 17, 0); text-decoration: underline; " href="http://hgbook.red-bean.com/"><font color="#5c81a7">http://hgbook.red-bean.com/</font></a>。</li>
</ul>
<blockquote>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a name="1" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">Mercurial&nbsp;</span></a>是一个轻量级的分布式版本控制系统，它以方便的控制、极强的扩展性赢得了众多开放源代码项目的青睐。本文从版本控制系统中的基本概念、操作和扩展性等方面，有侧重的介绍了 Mercurial。此外本文列出了几个其他常用的分布式版本控制系统，并和 Mercurial 作了简单的比较。通过阅读本文，读者可以了解基础的Mercurial操作，进而熟悉这个备受青睐的工具。</blockquote>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="1" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">Mercurial 简介</span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Mercurial 是一种轻量级分布式版本控制系统，采用 Python 语言实现，易于学习和使用，扩展性强。其是基于 GNU General Public License (GPL) 授权的开源项目。相对于传统的版本控制，具有如下优点：</div>
<ul style="list-style-type: none; list-style-position: initial; list-style-image: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">
    <li style="list-style-type: none; list-style-position: initial; list-style-image: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">更轻松的管理。传统的版本控制系统使用集中式的 repository，一些和 repository相关的管理就只能由管理员一个人进行。由于采用了分布式的模型，Mercurial 中就没有这样的困扰，每个用户管理自己的 repository，管理员只需协调同步这些repository。</li>
    <li style="list-style-type: none; list-style-position: initial; list-style-image: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">更健壮的系统。分布式系统比集中式的单服务器系统更健壮，单服务器系统一旦服务器出现问题整个系统就不能运行了，分布式系统通常不会因为一两个节点而受到影响。</li>
    <li style="list-style-type: none; list-style-position: initial; list-style-image: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">对网络的依赖性更低。由于同步可以放在任意时刻进行，Mercurial 甚至可以离线进行管理，只需在有网络连接时同步。</li>
    <hr />
</ul>
<div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="2" repository="" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">从 repository 开始</span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">版本控制系统中的 repository 就像一个仓库一样，用来存储被管理的数据文件，包含数据文件的不同版本。传统的版本控制系统中，这样的repository 是集中式的。除了这样一个集中式的 repository 之外，每个用户会有一份自己的工作版本拷贝。用户通过命令同步自己的拷贝和集中式的repository。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">分布式版本控制系统中的 repository 则采用的是对等网络式的方式。传统集中式的管理中，只有一份 repository，其他的只是工作拷贝，不包含额外的版本。分布式的管理当中，每个用户所持有的都是一个真实的 repository，当中存储有不同的版本信息和维护一个 repository 的必要的辅助元数据。这样一个对等工作模式当中，用户通过交换下文即将提到的 changeset 来完成同步。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">这样做的一些优点在于，工作的并行度将大大的提高。每个用户都可以带着这样的repository，从这里他可以把当前的工作拷贝切换到 repository 里面存储的任何一个版本。这个版本可以是之前正在工作的版本，现在需要合并进一些别人的意见，也可以是用户私有的一个版本，当前正在做很多前瞻性的工作，还没有能同步给其他用户使用。也同样是因为这样的模式，每个用户可以任意把自己的 repository 当中的一个版本交换给其他用户，而不需要对自己手头正在工作的版本进行回退。下图是这样一个灵活的工作模式的演示。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><br />
<a name="N10083" style="color: rgb(17, 17, 0); text-decoration: underline; "><b style="font-weight: bold; ">图 1. 工作模式的演示</b></a><br />
<img alt="工作模式的演示" width="554" height="87" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; max-width: 610px !important; " src="http://www.ibm.com/developerworks/cn/opensource/os-cn-mercurial/images/image001.gif" />&nbsp;</div>
<hr />
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="3" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">Mercurial 里的元素</span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="3" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Revision</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">在使用&nbsp;<a style="color: rgb(17, 17, 0); text-decoration: underline; " href="http://www.selenic.com/mercurial/wiki/index.cgi/Mercurial"><font color="#5c81a7">Mercurial</font></a>&nbsp;的系统中每个改动隔离在各自的 repository 里，既避免把不相关的代码混杂起来， 又便于一个接一个的测试每一部分工作，用户做的每个改动称为一个 revision。一般会有一个所有用户都可以访问得到的 repository 保存了项目的&ldquo;主要&rdquo;版本，工作repository 是用户自己做事情的地方，实现新的特性，修改漏洞，重构，实验等，当完成改变后，你可以 push 到共用的 repositor y中，即完成了一个 revision。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="3" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Changeset</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">一个或多个文件的改变集合在一起形成一个逻辑单元，称为 changeset。每一个 changeset由两部分内容描述，版本号和 changeset 标识，例如：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
	changeset:   207:58e4906e69e3 
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">冒号前面的数字代表版本号，它用来标识本地 changeset。这个版本号只有在用户的本地repository 中才有意义。冒号后面的那个很长的十六进制串是 changeset标识, 它是确定changeset的全局唯一标识符, 在所有包含这个 changese 的 repository 中都相同。多个用户之间讨论changeset，一般使用这个 changeset 标识，而不是上面说的版本号，因为完全有可能每个用户的 repository 中同样的 changeset 版本号不同。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="3" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Head</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Head 表示 repository 中每个分支最新的 revision，通常在合并几个分支时会用到这个概念。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="3" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Tip</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Tip 是最新的一个 changeset 的版本号的一个别名。在命令中任何使用版本号的地方都可以使用 tip 来代替最新的 changeset的版本号。Tip在各个repository中是不同的，同时一个repository 中只有一个 tip。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="3" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Log</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Log 命令按时间顺序从近到远的记录着在 repository 中发生的每一次事件。可以通过指定-v诊断输出选项来获得更多更详细的历史信息，或者指定&mdash;debug选项来获得历史信息中的一切细节。</div>
<hr />
<div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="4" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">动手操作起来</span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">以下是一些实际使用 Mercurial 中常用的例子。Mercurial 的原意是元素周期表当中的汞元素，但是 Mercurial 这样的单词显然不太适合日常使用。事实上 Mercurial 的命令取了元素周期表当中汞元素的化学符号：hg，所有的 Mercurial 命令都以 hg 开始。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
    $ hg command [options]
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">其中 command 是 Mercurial 的命令。每个命令的具体的命令行选项可以使用：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
    $ hg help command
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">来获得。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="4" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">克隆一个 repository</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">我们使用 clone 命令克隆一个 repository，它生成一个完整的 repository 复本，这样我们就有一个本地私有的 repository 来工作。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">例如：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
     $ hg clone  http://foo.com/hg/project1
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">如果所有都没问题，clone 命令输出：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
    destination directory: project1
    requesting all changes
	adding changesets
	adding manifests
	adding file changes
	added 127 changesets with 448 changes to 143 files
	139 files updated, 0 files merged, 0 files removed, 0 files 	unresolved
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">此时，我们应该在当前目录下发现一个目录叫 project1，目录下的文件是我们刚克隆的 repository 的精确复本。在 Mercurial 中，每一个 repository 是自包含的。当你克隆一个repository 后，新 repository 变成克隆时它的精确复本，但是后续的两个 repository 当中任一方改变都不会在对方显示，除非用户使用 pull 或 push 命令明确地传递改变，这个将在后面介绍。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">另外，每个用户可以使用 init 命令将本地的一个目录初始化为一个 Mercurial 的 repository，只需要在那个目录下运行：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
   $ hg init
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">如果设置好了同步共享的发布方式，其他用户就可以来克隆该用户的 repository 了。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="4" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">发布你的改动</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">进入工作目录，使用我们喜欢的编辑软件修改，例如我们要修改 main.py 让它增加打印一行输出：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
def main():
    print &quot;I'm in the a function.&quot;
    print &quot;Great joy of using Mercurial!&quot;  #新加的一行
if __name__ == &quot;__main__&quot;:
    sys.exit(main())
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">完成之后退出编辑器，任务完成。有了刚才的修改我们就可以创建一个changeset。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">在创建 changeset 之前如果想确认一下哪些文件被改动了，可以使用 status 命令。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
$ hg status
M main.py
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">使用 diff 命令可以检查实际文件内容的改变：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
diff -r a58db6f0e482 main.py
--- a/main.py   Thu Nov 29 13:38:38 2007 +0800
+++ b/main.py   Thu Nov 29 13:46:10 2007 +0800
@@ -1,5 +1,6 @@ def main():
 def main():
     print &quot;I'm in the a function.&quot;
+    print &quot;Great joy of using Mercurial!&quot; #新加的一行
 if __name__ == &quot;__main__&quot;:
     sys.exit(main())
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">diff 命令的默认输出是通用的补丁格式，易于在各种系统之间交换和讨论。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">创建一个 changeset 后我们就可以用 commit 命令提交了。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
$ hg commit
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">这个命令把我们带到一个编辑器内，缺省的编辑器是 vi，同时给我们展示了几行如下的文字：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
HG: user: Guolian Yun &lt;yunguol@cn.ibm.com&gt;
HG: changed main.py
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">第一行是空的，接下来的几行表明哪些文件将进入本 changeset。为了改变 changeset，我们必须描述它的原因，这通常称为 changeset注释。让我们输入一些：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
I&rsquo;m using Mercurial!
HG: user: Guolian Yun &lt;yunguol@cn.ibm.com&gt;
HG: changed main.py
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">接着，保存并退出编辑器，如果一切正常，commit 命令将没有任何提示地输出。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">让我们看看status命令现在告诉我们什么？</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
$ hg status
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">什么也没有！我们的改动已经提交到changeset里了，那里没有修改的文件需要提交的。Repository 中内容和当前工作目录的内容一致了。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">现在可以检查以下最新的改动是不是包含刚才所添加的 changeset 注释，使用 tip 命令就可以显示了：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
$ hg tip:
changeset:   2:2874393e3d9c
tag:         tip
user:        Guolian Yun &lt;yunguol@cn.ibm.com&gt;
date:        Thu Nov 29 10:10:39 2007 +0800
summary:     I'm using Mercurial!
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">目前新的 changeset 只存在本地 repository 中，如果想和其它 repository 分享改动，我们需要使用 push。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
$ hg push project2
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">project2 为你想要 push 的目标 repository 的名字。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="4" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">引入他人的改动</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">想要得到所有在别的 repository中而在本地repository中没有的改动，可以采用 pull命令。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
$ hg pull project3
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">project3为我们想要得到更新的目标repository的名字。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">在 Pull 后，缺省情况下Mercurial不更新工作目录。这意味着虽然repository现在有changeset，但在工作目录中的 main.py 文件仍然是 pull 之前老的内容。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">如果只想从hg clone的 repository 中更新当前 revision 到最新版，可以直接采用：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
$ hg pull -u
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="4" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Repository 之间的同步</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">上文当中的 push 和 pull 的操作，是处于不同位置的 repository 之间的同步。之前给出的两个例子是本地目录 repository 之间的同步。Mercurial 还支持以下形式的 repository 之间的同步：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
file://local/filesystem/path
http://[user@]host[:port]/[path]
https://[user@]host[:port]/[path]
ssh://[user@]host[:port]/[path]
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">其中 file 协议和本地目录相同。在 http 和 https 协议上使用push命令，需要在远端的服务器上启用相关的属性。ssh协议是众多系统中支持的shell。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">标准的 Mercurial 发行包中还附带一个 Python CGI 脚本 hgweb.cgi, 可以用来参考搭建一个多用户可以集中式的同步改动的界面，如下图所示：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><br />
<a name="N1018B" style="color: rgb(17, 17, 0); text-decoration: underline; "><b style="font-weight: bold; ">图 2. 界面</b></a><br />
<img alt="界面" width="510" height="186" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; max-width: 610px !important; " src="http://www.ibm.com/developerworks/cn/opensource/os-cn-mercurial/images/image002.gif" /></div>
<hr />
</div>
</div>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="5" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">扩展 Mercurial</span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Mercurial 系统中提供一种扩展机制来添加新的命令。通过扩展添加的命令可以在现有的Mercurial 系统的基础上添加新的功能，这些命令跟随&nbsp;<code><font face="NSimsun">hg&nbsp;</font></code>后被调用时就像原生的命令一样。本文介绍两个常用的Mercurial扩展：Patchbomb和Mq。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="5" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Patchbomb</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Patchbomb是一个在Mercurial系统中利用发送邮件的方式来交换changeset的扩展。Patchbomb添加了一个新的<code><font face="NSimsun">email</font></code>命令。通过调用&nbsp;<code><font face="NSimsun">hg email&nbsp;</font></code>命令，changeset 提交时的信息的第一行将作为邮件的主题，信件的正文包括完整的 changese t提交信息，以 patch 的形式发布出来的 changeset 完整补丁。如果一次发送的是多个changeset，那么Patchbomb会提示输入本次 changeset 集的总提示信息，这部分信息将作为第一封信，信件主题以<code><font face="NSimsun">[PATCH 0 of N]</font></code>开头，changeset 则会以<code><font face="NSimsun">[PATCH i of N]</font></code>将的主题开头发出，其中<code><font face="NSimsun">i</font></code>是 changeset在本地 repository 当中的顺序。多changeset 系列邮件中，每封信会在邮件头中包含合适的回复信息，这样在邮件客户端可以清晰的显示出系列 changeset 之间的层次关系。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><br />
<a name="N101C3" style="color: rgb(17, 17, 0); text-decoration: underline; "><b style="font-weight: bold; ">图 3. 层次关系</b></a><br />
<img alt="层次关系" width="554" height="120" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; max-width: 610px !important; " src="http://www.ibm.com/developerworks/cn/opensource/os-cn-mercurial/images/image003.gif" />&nbsp;</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Patchbomb 支持使用本地系统中的 sendmail 程序来发送邮件，同时支持使用 SMTP 邮件服务器。用户如果长期固定为某个项目工作，还可以将邮件的收件地址和发信地址提供给Patchbomb，免去每次手动输入的麻烦。这一切都可以在 Mercurial 统一的&nbsp;<code><font face="NSimsun">.hgrc&nbsp;</font></code>当中设置，以下是一个完整的例子。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
[extensions]
hgext.patchbomb =
[email]
method = smtp # 还可以在这里指定/usr/sbin/sendmail
from = Zhengang Li &lt;lizg@cn.ibm.com&gt;
to = groupmail@foo.com
[smtp]
host = smtp.foo.com
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Patchbomb 作者为Bryan O&rsquo;Sullivan，该扩展现在随同 Mercurial 系统一起发布，用户不需额外下载安装，只需如上例中一样启用即可。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="5" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="smalltitle"><strong style="font-weight: bold; "><font size="3" face="Arial">Mq</font></strong></span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Mq 扩展的全名是Mercurial Queues，顾名思义该扩展将用户本地的多个 changeset 排列到队列中。原先分布式版本控制系统中，changeset 一旦提交并不能修改。有了 Mq 扩展之后，用户可以将本地的任意数量的 changeset 存放至一个本地的队列当中，对这些 changeset 用户除了可以使用传统的 changeset 上的任何命令之外，还可以修改changeset，包括提交信息和版本补丁的改动。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">启用 Mq 扩展的办法同其他扩展一样，在&nbsp;<code><font face="NSimsun">.hgrc&nbsp;</font></code>当中添加如下信息：</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<table border="0" cellspacing="0" cellpadding="0" width="100%" style="color: rgb(51, 51, 51); font: normal normal normal 12px/normal Verdana, Arial, Helvetica, 宋体, sans-serif; ">
    <tbody>
        <tr>
            <td class="code-outline" style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; color: rgb(0, 0, 0); ">
            <pre class="displaycode" style="font-family: 'Courier New', monospace; font-size: 12px; width: 623px; overflow-x: auto; overflow-y: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 247, 247); background-position: initial initial; background-repeat: initial initial; ">
[extensions]
hgext.mq=
</pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Mq的命令是一系列以字母q打头的命令，<code><font face="NSimsun">qinit</font></code>,&nbsp;<code><font face="NSimsun">qnew</font></code>,&nbsp;<code><font face="NSimsun">qrefresh</font></code>,&nbsp;<code><font face="NSimsun">qdiff</font></code>,&nbsp;<code><font face="NSimsun">qpop和qpush</font></code>等。<code><font face="NSimsun">Qinit&nbsp;</font></code>用来初始化用来存放补丁队列的目录，<code><font face="NSimsun">qnew</font></code>创建一个新的补丁changeset，<code><font face="NSimsun">qrefresh&nbsp;</font></code>将改动刷新到当前的补丁当中去，<code><font face="NSimsun">qdiff&nbsp;</font></code>将当前的补丁打印到屏幕，<code><font face="NSimsun">qpop&nbsp;</font></code>和&nbsp;<code><font face="NSimsun">qpush&nbsp;</font></code>用来移动当前存放在队列顶部的补丁。完整的 q 系列命令可以从&nbsp;<code><font face="NSimsun">hg help</font></code>给出的列表中获得。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Mq中所有的 changeset 补丁存放在项目顶层目录的<code><font face="NSimsun">.hg/patches</font></code>下面，用户可以手动修改这些补丁当中的提交信息。Changeset 补丁的顺序存放在<code><font face="NSimsun">.hg/patches/series文件当中，同样的，用户可以修改这些补丁的顺序。</font></code></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Mq的作者是Chris Mason，该扩展现在随同 Mercurial 系统一起发布，用户不需额外下载安装。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">如果现有的扩展不能满足用户的要求，编写自己的扩展也不困难。Mercurial 使用 Python编写，编写一个新的扩展相当于在 Mercurial 系统的 hgext 包当中编写一个新的模块。具体的扩展实现还有些约定的规则，用户可以参考 Mercurial 所提供的文档。</div>
<hr />
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="6" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">其他分布式版本控制系统</span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">分布式版本控制系统领域还有一些其他的系统，如GNU arch，monotone，Bazaar，git，darcs。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">各类系统在各在一定的领域内长处，如GNU arch在GNU Savannah主机上应用，Bazaar 主要用于 Ubuntu Linux 系统的开发当中，git 源于Linux kernel 的开发，现在在多处和内核相关的项目中使用。他们大多数提供友好的Web界面和多种版本同步协议的支持。Git 和Gnu arch 由 C 和 shell 脚本语言编写实现，monotone 由C++语言实现，darcs 由 Haskell语言实现，Bazaar 和本文介绍的 Mercurial 由 Python 语言实现。从开放和扩展性方面来说，类似 Python 这样的脚本语言的更易于用户编写自己的扩展。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">在众多的分布式版本控制系统中，Mercurial 是最年轻的，它的第一个版本发布于2005年4月。Mercurial 吸收了众多前辈的特性，被众多的项目采用。</div>
<hr />
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; "><a name="7" style="color: rgb(17, 17, 0); text-decoration: underline; "><span class="atitle">结束语</span></a></div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">Mercurial 基本的概念和操作熟悉之后，读者可以进一步阅读参考资料当中的文献，进一步了解Mercurial 的系统维护和实现细节。</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">&nbsp;</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">&nbsp;</div>
<div style="margin-top: 0px; margin-right: auto; margin-bottom: 0px; margin-left: auto; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; ">KINGFO：其他指南&nbsp;<a href="http://hgbook.red-bean.com/read/">http://hgbook.red-bean.com/read/</a></div>
</div>
</div>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/tip_css_input.aspx]]></link>
	<title><![CDATA[每日一Tip_CSS_input]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-4-29 9:39:49</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/tip_css_input.aspx]]></guid>
	<description><![CDATA[<blockquote>
<p>&nbsp;</p>
<p>&nbsp;对于input框，在定义高度后在ie下会出现各种很怪异的问题，所以我们一般不定义input框的高度，通过padding值来控制</p>
</blockquote>
<p>--------来自团队的总结</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/learning_advanced_javascript.aspx]]></link>
	<title><![CDATA[Learning Advanced JavaScript]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-4-16 12:27:59</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/learning_advanced_javascript.aspx]]></guid>
	<description><![CDATA[<p>&nbsp;</p>
<p><a href="http://ejohn.org/apps/learn/">&nbsp;http://ejohn.org/apps/learn/</a></p>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/javaScript_oop_framework_in_200_lines.aspx]]></link>
	<title><![CDATA[[转]200行实现JavaScript OOP 框架]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-4-2 9:31:55</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/javaScript_oop_framework_in_200_lines.aspx]]></guid>
	<description><![CDATA[<dl id="meta"><dt>来自：http://corodidea.net/blog/index.php/archives/129<br />
</dt><dt>作者</dt><dd><a href="http://corodidea.net/">infinte</a></dd><dt>关键词</dt><dd>JavaScript, OOP, 框架, 运行时覆写, 保护成员</dd><dt>摘要</dt><dd>
<p>本文主要实现了一个轻量的JavaScript  OOP框架，并借此讨论了基于运行时覆写实现基类方法调用的技术以及实现保护成员的方法。<br />
A lightweight JavaScript OOP framework was implemented in this text.  Base-method invocation implementation technique, using runtime  overwriting, and implementation of protected members was discussed here.</p>
</dd></dl>
<p>我终于这个优雅且几乎完美的JavaScript OOP 实现&mdash;&mdash;轻便，简洁，并且有效。(暂且命名为emop)    <br />
Finally I've found the elegant implementation of almost-perfect  OOP framework implementation in Javascript. It's light, clear, and,  effective.(temporarily named emop)</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;Class;&nbsp;</span></span></li><li><span><span class="keyword">void</span><span>&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;mgBaseGen&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(bcl,&nbsp;original)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">function</span><span>(nname)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;c&nbsp;=&nbsp;bcl,&nbsp;rv;&nbsp;</span></span></li><li><span><span class="keyword">while</span><span>&nbsp;(c&nbsp;&amp;&amp;&nbsp;!c.prototype.hasOwnProperty(nname))&nbsp;c&nbsp;=&nbsp;c.baseConstructor;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(!c)&nbsp;</span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'Cannot&nbsp;find&nbsp;base&nbsp;class&nbsp;with&nbsp;specific&nbsp;methods'</span><span>);&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;mgBaseGen(c.baseConstructor,&nbsp;</span><span class="keyword">this</span><span>.base);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li><span>rv&nbsp;=&nbsp;c.prototype[nname].apply(<span class="keyword">this</span><span>,&nbsp;Array.prototype.slice.call(arguments,&nbsp;1));&nbsp;</span></span></li><li class="alt"><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;original;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">return</span><span>&nbsp;rv;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>};&nbsp;</span></li><li class="alt"><span><span class="comment">//&nbsp;Token</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;CHECK&nbsp;=&nbsp;{};&nbsp;</span></span></li><li class="alt"><span><span class="comment">//&nbsp;Empty&nbsp;function</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;NULLFUNC&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{};&nbsp;</span></span></li><li class="alt"><span><span class="comment">//&nbsp;hasOwnProperty&nbsp;checker</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;HOPCHECKER&nbsp;=&nbsp;{};&nbsp;</span></span></li><li class="alt"><span><span class="comment">//&nbsp;protected&nbsp;properties&nbsp;name</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;protectedName&nbsp;=&nbsp;</span><span class="string">'..protected..'</span><span>;&nbsp;</span></span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;registerProtecteds&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(o)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;protecteds&nbsp;=&nbsp;[];&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;p&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(checker,&nbsp;name,&nbsp;value)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(checker&nbsp;!==&nbsp;CHECK)&nbsp;</span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'access&nbsp;denied'</span><span>);&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(arguments.length&nbsp;&gt;&nbsp;2)&nbsp;</span><span class="keyword">return</span><span>&nbsp;protecteds[name]&nbsp;=&nbsp;value;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(HOPCHECKER.hasOwnProperty.call(protecteds,&nbsp;name))&nbsp;</span><span class="keyword">return</span><span>&nbsp;protecteds[name];&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>p.length&nbsp;=&nbsp;0;&nbsp;</span></li><li><span>p.toString&nbsp;=&nbsp;<span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'access&nbsp;denied'</span><span>)&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>o[protectedName]&nbsp;=&nbsp;p;&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;bound&nbsp;=&nbsp;</span><span class="keyword">null</span><span>;&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;priv&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(n,&nbsp;v)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(!HOPCHECKER.hasOwnProperty.call(bound,&nbsp;protectedName))&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(protectedName&nbsp;</span><span class="keyword">in</span><span>&nbsp;bound)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>registerProtecteds(bound);&nbsp;</span></li><li><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'access&nbsp;denied'</span><span>);&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li><li><span><span class="keyword">if</span><span>&nbsp;(arguments.length&nbsp;&gt;&nbsp;1)&nbsp;</span><span class="keyword">return</span><span>&nbsp;bound[protectedName](CHECK,&nbsp;n,&nbsp;v);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">else</span><span>&nbsp;</span><span class="keyword">return</span><span>&nbsp;bound[protectedName](CHECK,&nbsp;n);&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;wrapProtected&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(method)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;hold&nbsp;=&nbsp;bound;&nbsp;</span></span></li><li class="alt"><span>bound&nbsp;=&nbsp;<span class="keyword">this</span><span>;&nbsp;</span></span></li><li><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;ret&nbsp;=&nbsp;method.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span>bound&nbsp;=&nbsp;hold;&nbsp;</span></li><li><span><span class="keyword">return</span><span>&nbsp;ret;&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span>}&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="comment">//&nbsp;catalogs</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;NClassBase&nbsp;=&nbsp;</span><span class="keyword">null</span><span>;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;NAttachments&nbsp;=&nbsp;[];&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span>Class&nbsp;=&nbsp;<span class="keyword">function</span><span>(Definition,&nbsp;proto)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="comment">//&nbsp;stack&nbsp;backup</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;BClassBase&nbsp;=&nbsp;NClassBase;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;BAttachments&nbsp;=&nbsp;NAttachments;&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="comment">//&nbsp;clear&nbsp;attachments&nbsp;array</span><span>&nbsp;</span></span></li><li><span>NAttachments&nbsp;=&nbsp;[];&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="comment">//&nbsp;constructor</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;ctor,&nbsp;def&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Definition(priv);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(def.initalize&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li><span>ctor&nbsp;=&nbsp;wrapProtected(def.initalize);&nbsp;</span></li><li class="alt"><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span></span></li><li><span>ctor&nbsp;=&nbsp;NULLFUNC;&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">delete</span><span>&nbsp;def.initalize;&nbsp;</span></span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="comment">//&nbsp;create&nbsp;class</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;Clz&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span>registerProtecteds(<span class="keyword">this</span><span>);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;ctor.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="comment">//bind&nbsp;prototype</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(proto&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function&nbsp;||&nbsp;NClassBase&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(proto&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>Clz.prototype&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;proto;&nbsp;</span></span></li><li><span>Clz.baseConstructor&nbsp;=&nbsp;proto;&nbsp;</span></li><li class="alt"><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(NClassBase&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li><span>Clz.prototype&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;NClassBase;&nbsp;</span></span></li><li class="alt"><span>Clz.baseConstructor&nbsp;=&nbsp;NClassBase;&nbsp;</span></li><li><span>};&nbsp;</span></li><li class="alt"><span>Clz.prototype.base&nbsp;=&nbsp;<span class="keyword">function</span><span>(name)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;c&nbsp;=&nbsp;Clz.baseConstructor,&nbsp;rv,&nbsp;cler&nbsp;=&nbsp;arguments.callee.caller.caller;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;original&nbsp;=&nbsp;</span><span class="keyword">this</span><span>.base;&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;mgBaseGen(c,&nbsp;original);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li><span>rv&nbsp;=&nbsp;<span class="keyword">this</span><span>.base.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li class="alt"><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;original;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">return</span><span>&nbsp;rv;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(proto)&nbsp;Clz.prototype&nbsp;=&nbsp;proto;&nbsp;</span></span></li><li><span><span class="keyword">else</span><span>&nbsp;Clz.prototype&nbsp;=&nbsp;{};&nbsp;</span></span></li><li class="alt"><span>Clz.baseConstructor&nbsp;=&nbsp;Object;&nbsp;<span class="comment">//&nbsp;need&nbsp;to&nbsp;be&nbsp;fixed;</span><span>&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>proto&nbsp;=&nbsp;Clz.prototype;&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="comment">//attachments</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">var</span><span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;NAttachments.length;&nbsp;i++)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;item&nbsp;=&nbsp;NAttachments[i][0];&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;args&nbsp;=&nbsp;[proto].concat(NAttachments[i][1]);&nbsp;</span></span></li><li><span>item.apply(proto,&nbsp;args);&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="comment">//reflect&nbsp;methods</span><span>&nbsp;</span></span></li><li><span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">var</span><span>&nbsp;each&nbsp;</span><span class="keyword">in</span><span>&nbsp;def)&nbsp;</span><span class="keyword">if</span><span>&nbsp;(def.hasOwnProperty(each))&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(def[each]&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;f&nbsp;=&nbsp;wrapProtected(def[each]);&nbsp;</span></span></li><li class="alt"><span>f.toString&nbsp;=&nbsp;<span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;def[each].toString()&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>f.length&nbsp;=&nbsp;def[each].length;&nbsp;</span></li><li class="alt"><span>proto[each]&nbsp;=&nbsp;f;&nbsp;</span></li><li><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span>proto[each]&nbsp;=&nbsp;def[each];&nbsp;</span></li><li><span>}&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li><span>NClassBase&nbsp;=&nbsp;BClassBase;&nbsp;</span></li><li class="alt"><span>NAttachments&nbsp;=&nbsp;BAttachments;&nbsp;</span></li><li><span><span class="keyword">return</span><span>&nbsp;Clz;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>};&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>Class.base&nbsp;=&nbsp;<span class="keyword">function</span><span>(f)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>NClassBase&nbsp;=&nbsp;f;&nbsp;</span></li><li><span>};&nbsp;</span></li><li class="alt"><span>Class.attach&nbsp;=&nbsp;<span class="keyword">function</span><span>(attachment,&nbsp;_args_)&nbsp;{&nbsp;</span></span></li><li><span>NAttachments.push([attachment,&nbsp;Array.prototype.slice.call(arguments,&nbsp;1)]);&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>Function.prototype.derive&nbsp;=&nbsp;<span class="keyword">function</span><span>(definition)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;Class(definition,&nbsp;</span><span class="keyword">this</span><span>);&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>Function.prototype.asClass&nbsp;=&nbsp;<span class="keyword">function</span><span>(base)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;Class(</span><span class="keyword">this</span><span>,&nbsp;base);&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>}();&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="comment">//Usage</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;Greeter&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.greet&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span>alert(<span class="string">'hello!'</span><span>);&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;A&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(priv)&nbsp;{&nbsp;</span></span></li><li><span>Class.attach(Greeter);&nbsp;</span></li><li class="alt"><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li><span>priv(<span class="string">'y'</span><span>,&nbsp;t);&nbsp;</span></span></li><li class="alt"><span>alert(priv(<span class="string">'y'</span><span>));&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>}.asClass();&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;B&nbsp;=&nbsp;A.derive(&nbsp;</span><span class="keyword">function</span><span>(priv)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;Point&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">this</span><span>.initalize&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(x,&nbsp;y)&nbsp;{&nbsp;</span></span></li><li><span>p(<span class="string">'x'</span><span>,&nbsp;x);&nbsp;</span></span></li><li class="alt"><span>p(<span class="string">'y'</span><span>,&nbsp;y);&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span><span class="keyword">this</span><span>.abs&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;x&nbsp;=&nbsp;p(</span><span class="string">'x'</span><span>);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;y&nbsp;=&nbsp;p(</span><span class="string">'y'</span><span>);&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;Math.sqrt(x&nbsp;*&nbsp;x&nbsp;+&nbsp;y&nbsp;*&nbsp;y);&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>}.asClass();&nbsp;</span></li><li class="alt"><span><span class="keyword">this</span><span>.g&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(p,&nbsp;q)&nbsp;{&nbsp;</span></span></li><li><span>alert((<span class="keyword">new</span><span>&nbsp;Point(p,&nbsp;q)).abs());&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">this</span><span>.base(</span><span class="string">'f'</span><span>,&nbsp;t);&nbsp;</span></span></li><li><span>alert(<span class="string">'--&nbsp;'</span><span>&nbsp;+&nbsp;t);&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span><span class="keyword">this</span><span>.inter&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(obj,&nbsp;t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>obj.f(t)&nbsp;</span></li><li><span>};&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;foo&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;</span></span></li><li><span>foo.greet();&nbsp;</span></li><li class="alt"><span>foo.f(2);&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;foo2&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;</span></span></li><li class="alt"><span>foo2.g(5,&nbsp;5);&nbsp;</span></li><li><span>foo2.inter(foo,&nbsp;3);&nbsp;</span></li></ol></pre>
<p>&nbsp;</p>
<h2>这是什么？    <br />
What is it?</h2>
<p>长期以来JavaScript程序员感到JavaScript的诸多掣肘之一就是它没有&ldquo;完整的&rdquo;OOP支持。尽管JavaScript利用原型系 统提供了OOP功能，但它没有提供这些特性：保护成员和基类方法调用。这段代码就是为了解决此问题。    <br />
For a long time, one of its limits which JavaScript programmers  found is that it cannot provide &quot;complete&quot; OOP support. Although OOP was  provided by the prototype system, the following charactics are absent:  protected members and base method invocation. The target of this code is  to solve this problem.</p>
<h2>基本思想    <br />
Basic concepts</h2>
<ul>
    <li>使用闭包独立环境      <br />
    Isolate environments by using closures</li>
    <li>运行时覆写      <br />
    Runtime overwriting</li>
    <li>使用try-finally的异常处理      <br />
    Exception handling via try-catch</li>
</ul>
<h2>定义类    <br />
Defining class</h2>
<p>定义类的是一个函数，和传统的JavaScript构造器类似：    <br />
What defines a class is a function, written in thetraditional way:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">function</span><span>(priv)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.g&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>priv(<span class="string">'x'</span><span>,&nbsp;t);&nbsp;</span></span></li><li><span>alert(priv(<span class="string">'x'</span><span>));&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">this</span><span>.base(</span><span class="string">'f'</span><span>,&nbsp;t);&nbsp;</span></span></li><li><span>alert(<span class="string">'--&nbsp;'</span><span>&nbsp;+&nbsp;t);&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span>}&nbsp;</span></li></ol></pre>
<p>你可以看见类似传统&ldquo;构造器&rdquo;的东西&mdash;&mdash;用<code>this.methodName</code>定义方法。不过，这里有一个很奇怪的<code>priv</code>参 数&mdash;&mdash;它就是保护乘员的读写器。类定义将会传入<code>Class</code>函数，经过一系列复杂的转化后，返回我们需要的构造器。获得这个类只 要通过下面一句：    <br />
You can see something like traditional JavaScript  constructors--defineing methods via &quot;<code>this.methodName</code>&quot;. But,  a strange method named &quot;<code>priv</code>&quot; appears here.It's the  accessor of protected members. Such class definition will be sent into  <code>Class</code>, and after a series of complicated transformation,  the constructor we need yields.Getting this class can even use only one  statement:</p>
<pre><ol class="dp-c"><li class="alt"><span><span>A&nbsp;=&nbsp;Class(definition,&nbsp;base)&nbsp;</span></span></li></ol></pre>
<p>第一个参数是定义，第二个是其基类。    <br />
The first argument is the definition, the second is its base  class.</p>
<p>emop还有两个语法糖：一个是<code>Function.prototype.asClass</code>，另一个是<code>Function.prototype.derive</code>。 它们分别定义为：   <br />
There are also 2 syntax sugars in emop: one is <code>Function.prototype.asClass</code>,  the other is  <code>Function.prototype.derive</code>. Their definitions are:</p>
<pre><ol class="dp-xml"><li class="alt"><span><span class="attribute">Function.prototype.derive</span><span>&nbsp;=&nbsp;</span><span class="attribute-value">function</span><span>(definition)&nbsp;{&nbsp;</span></span></li><li><span>return&nbsp;Class(definition,&nbsp;this);&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="attribute">Function.prototype.asClass</span><span>&nbsp;=&nbsp;</span><span class="attribute-value">function</span><span>(base)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>return&nbsp;Class(this,&nbsp;base);&nbsp;</span></li><li><span>}&nbsp;</span></li></ol></pre>
<h3>细节    <br />
In depth</h3>
<p>你已经看到了，一个类定义很像一个构造器，但事实上不是。类定义是个函数，而且真的会运行，但只会运行一次。事实上构造器是由其定义的<code>initalize</code>方 法描述：    <br />
You have seen that a class definition looks like a constructor,  but it in't. Class definition is a function, and it will be invoked, but  only once. Actually, the exact constructor is described by  <code>initalize </code>method which the definition defines:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;Point&nbsp;=&nbsp;Class(</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.initalize&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(x,&nbsp;y)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>p(<span class="string">'x'</span><span>,&nbsp;x);&nbsp;</span></span></li><li><span>p(<span class="string">'y'</span><span>,&nbsp;y);&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">this</span><span>.abs&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;x&nbsp;=&nbsp;p(</span><span class="string">'x'</span><span>);&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;y&nbsp;=&nbsp;p(</span><span class="string">'y'</span><span>);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;Math.sqrt(x&nbsp;*&nbsp;x&nbsp;+&nbsp;y&nbsp;*&nbsp;y);&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li></ol></pre>
<p>上面的<code>Point</code>是一个极好的例子。当我们要构造一个点的时候，虽然代码像下面的这样：    <br />
The <code>Point </code>above is a good example. When we need to  construction a point, the following code appears:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;p1&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Point(0,&nbsp;0);&nbsp;</span></span></li></ol></pre>
<h2>特性    <br />
Charactics</h2>
<p>你可能已经发现第一段代码中有几个很有趣的方法：    <br />
Maybe you've found some interesting methods in the first code  paragraph:</p>
<ul>
    <li><code>Class.attach </code></li>
    <li><code>Class.base </code></li>
    <li><code>&ldquo;priv&rdquo; </code></li>
    <li><code>(instance).base </code></li>
</ul>
<p>上面几个&ldquo;特殊&rdquo;方法的用途分别是：    <br />
Usages of the &quot;special&quot; methods are:</p>
<ul>
    <li>附加相关的&ldquo;附件&rdquo;（混入类）      <br />
    Attach specific &quot;Attachments&quot;(mixins)</li>
    <li>指定基类      <br />
    Define base class</li>
    <li>存取&ldquo;保护成员&rdquo;      <br />
    Access &quot;protected members&quot;</li>
    <li>调用&ldquo;基类&rdquo;方法      <br />
    Invoke base methods</li>
</ul>
<h3><code>priv</code></h3>
<p>因为类定义是一个函数，它的第一个参数就是存取保护成员的读写器。在emop中一个对象拥有一般成员（和JavaScript中的一样）和保护成员 （只能用这个读写器访问）。因为方法定义总是包含在类定义中，所以<code>priv</code>可以被访问到，对象方法可以使用<code>priv</code>读 写保护成员：    <br />
Because class definition is a function, it's first paramater is  the accessor of protected memners. Objects in emop contains normal  members (like that in native JavaScript object) and protected  members(only accessable by this accessor). Because the method definition  is always contained by class definition,  <code>priv </code>can be accessed and methods can use it to access  protected members:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">this</span><span>.m&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span>priv(<span class="string">'x'</span><span>);&nbsp;</span><span class="comment">//&nbsp;get</span><span>&nbsp;</span></span></li><li class="alt"><span>priv(<span class="string">'x'</span><span>,&nbsp;1);&nbsp;</span><span class="comment">//&nbsp;set</span><span>&nbsp;</span></span></li><li><span>}&nbsp;</span></li></ol></pre>
<p>在这个例子中，<code>m</code>方法可以自由读写<code>'x'</code>保护成员。但<code>priv</code>在 类定义外就不能访问了，所以外界不能经过<code>priv</code>读写保护成员。    <br />
In this example, method <code>m</code> can access protected member  <code>'x'</code> freely. But  <code>priv </code>is not accessable outside the class definiton, so  outside program cannot access protected members via  <code>priv</code>.</p>
<p><code>priv</code>有两种调用方法：    <br />
There are two ways to invoke <code>priv</code>:</p>
<pre><ol class="dp-c"><li class="alt"><span><span>priv(</span><span class="string">'x'</span><span>);&nbsp;</span><span class="comment">//&nbsp;get</span><span>&nbsp;</span></span></li><li><span>priv(<span class="string">'x'</span><span>,&nbsp;1);&nbsp;</span><span class="comment">//&nbsp;set</span></span></li></ol></pre>
<p>&nbsp;</p>
<p>传入一个参数意味着读取，传入两个参数就是写入。    <br />
Passing one argument means reading, two means writing.</p>
<p>因为是保护成员，所以基类定义的方法和派生类定义的方法都可以使用<code>priv</code>访问。    <br />
Because it is protected members, base methods and derived methods  can both access it via  <code>priv</code>.</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;A&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span>p(<span class="string">'x'</span><span>,&nbsp;1)&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;B&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">this</span><span>.g&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;p(</span><span class="string">'x'</span><span>)&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span>},A);&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;obj&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;</span></span></li><li class="alt"><span>obj.f();&nbsp;</span></li><li><span>obj.g();&nbsp;<span class="comment">//&nbsp;--&gt;&nbsp;1&nbsp;</span><span>&nbsp;</span></span></li></ol></pre>
<h3><code>Class.base</code> and <code>Class.attach</code></h3>
<p>emop规定一个类只有一个基类，<code>Class.base</code>就描述基类。而<code>Class.attch</code>则 描述了混入类。混入类定义类似类定义，但它是直接<code>apply</code>到某类的<code>prototype</code>上。显然， 混入类不能拿到保护成员读写器<code>priv</code>。上面的那段代码可以改写成：<br />
emop declared that a class have only one base class, and it is defined  by <code>Class.base</code>.  <code>Class.attach</code> describes mixins. Mixin definition looks like  class definition, but it is directly  <code>apply</code>-ed to the <code>prototype</code> of some class.  Obviously, mixins cannot get protected member acceessor &quot;<code>priv</code>&quot;.  Code above can be written like:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;A&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span>p(<span class="string">'x'</span><span>,&nbsp;1)&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;B&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>Class.base(A);&nbsp;</span></li><li><span><span class="keyword">this</span><span>.g&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;p(</span><span class="string">'x'</span><span>)&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;obj&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;</span></span></li><li><span>obj.f();&nbsp;</span></li><li class="alt"><span>obj.g();&nbsp;<span class="comment">//&nbsp;1&nbsp;</span><span>&nbsp;</span></span></li></ol></pre>
<p>因此，定义派生类有两种方法：    <br />
So, derived class can be defined in two ways:</p>
<pre><ol class="dp-c"><li class="alt"><span><span>Derived&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{......&nbsp;</span></span></li><li><span>},Base)&nbsp;</span></li><li class="alt"><span>Derived&nbsp;=&nbsp;Class(&nbsp;<span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span>Class.base(Base);......&nbsp;</span></li><li class="alt"><span>})&nbsp;</span></li></ol></pre>
<p>下面的情况下，<code>Base1</code>是<code>Derived</code>的基类。另一个被抛弃：    <br />
Under the following situation, <code>Base1</code> is the base  class of  <code>Derived</code>, Not <code>Base2</code></p>
<pre><ol class="dp-c"><li class="alt"><span><span>Derived&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span>Class.base(Base2);......&nbsp;</span></li><li class="alt"><span>},Base1)&nbsp;</span></li></ol></pre>
<p>混入类可以参数化&mdash;&mdash;当调用<code>Class.attach(mixin,a,b,c)</code>时，传入<code>mixin</code>的 第一个参数是被定义类的<code>prototype</code>，接着是<code>a,b,c</code>。传入的<code>this</code>指 针也是那个<code>prototype</code>：    <br />
Mixins can be parameterized -- When invoking <code>Class.attach(mixin,a,b,c)</code>,  First argument passed into  <code>mixin </code>is the <code>prototype</code> of defined class,  following arguments are  <code>a,b</code> and <code>c</code>. <code>this</code> pointer passed is  also that  <code>prototype</code>.</p>
<pre><ol class="dp-c"><li class="alt"><span><span>Mix&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(proto,&nbsp;a)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;a&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;Thing&nbsp;=&nbsp;Class(&nbsp;</span></span></li><li><span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span>Class.attach(Mix,&nbsp;1);&nbsp;</span></li><li><span>});&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;t&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Thing;&nbsp;</span></span></li><li class="alt"><span>t.f()&nbsp;<span class="comment">//&nbsp;--&gt;&nbsp;1</span><span>&nbsp;</span></span></li></ol></pre>
<h3><code>(instance).base</code></h3>
<p>每个用<code>Class</code>创建的类构造的对象都有一个<code>base</code>用于调用基类方法。类似这样：    <br />
Each object constructed by a <code>Class</code>-defined class  contains the  <code>base</code> as a base-method invoker. Like this:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;A&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;t&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;B&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>Class.base(A);&nbsp;</span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;</span><span class="string">'x'</span><span>&nbsp;+&nbsp;</span><span class="keyword">this</span><span>.base(</span><span class="string">'f'</span><span>,&nbsp;t)&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;obj&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;</span></span></li><li><span>obj.f(1);&nbsp;<span class="comment">//&nbsp;--&gt;&nbsp;x1</span><span>&nbsp;</span></span></li></ol></pre>
<p>传入给<code>base</code>的第一个参数是要调用的基方法名，接着是参数。<code>base</code>会搜索其基类，如果它定义了 指定的方法，就执行之，否则继续向上，直到确认在所有基类中都找不到为止。    <br />
First argument passed into <code>base</code> is the method name we  want to invoke, then &quot;actual&quot; arguments.  <code>base</code> will search its base class, invoke the specified  method if the base class defined it, or continue going up until it  confirmed the method is absent in all base class definitions.</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;A&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;t&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>});&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;B&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>Class.base(A);&nbsp;</span></li><li><span>});&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;C&nbsp;=&nbsp;Class(&nbsp;</span><span class="keyword">function</span><span>(p)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>Class.base(B);&nbsp;</span></li><li><span><span class="keyword">this</span><span>.f&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(t)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;</span><span class="string">'x'</span><span>&nbsp;+&nbsp;</span><span class="keyword">this</span><span>.base(</span><span class="string">'f'</span><span>,&nbsp;t)&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span><span class="keyword">this</span><span>.g&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.base(</span><span class="string">'g'</span><span>)&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span>});&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;obj&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;C();&nbsp;</span></span></li><li class="alt"><span>obj.f(1);&nbsp;<span class="comment">//&nbsp;--&gt;&nbsp;x1</span><span>&nbsp;</span></span></li><li><span>obj.g();&nbsp;<span class="comment">//&nbsp;--&gt;&nbsp;Error:&nbsp;Method&nbsp;&quot;g&quot;&nbsp;absent</span><span>&nbsp;</span></span></li></ol></pre>
<h2>实现技术    <br />
Implementation Techniques</h2>
<h3>运行时覆写    <br />
Runtime Overwriting</h3>
<h4>回溯法的例子    <br />
Examples in backtracking algorithms</h4>
<p>想象一下我们在书写一个迷宫程序。迷宫由若干<code>cell</code>组成，我们的目的是看有没有去出口的路径。这种问题很适合用回溯 法，算法的框架大体如下：    <br />
Imagine that we're writing a maze program. A maze consists of some<code>  cell</code>, and we're going to find out whether the way to the exit  exists. This problem is suit for backtracking. The algorithm looks like  this:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;found&nbsp;=&nbsp;</span><span class="keyword">false</span><span>,&nbsp;steps&nbsp;=&nbsp;0;&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">function</span><span>&nbsp;searchCell(position)&nbsp;{&nbsp;</span></span></li><li><span>position.visited&nbsp;=&nbsp;<span class="keyword">true</span><span>;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(position&nbsp;==&nbsp;maze.exit)&nbsp;{&nbsp;</span></span></li><li><span>found&nbsp;=&nbsp;<span class="keyword">true</span><span>;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>steps&nbsp;+=&nbsp;1;&nbsp;</span></li><li><span><span class="keyword">var</span><span>&nbsp;neighbors&nbsp;=&nbsp;position.getNeighbors();&nbsp;</span></span></li><li class="alt"><span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">var</span><span>&nbsp;each&nbsp;</span><span class="keyword">in</span><span>&nbsp;neighbors)&nbsp;</span><span class="keyword">if</span><span>&nbsp;(!neighbors[each].visited)&nbsp;{&nbsp;</span></span></li><li><span>searchCell(neighbors[each]);&nbsp;</span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(found)&nbsp;</span><span class="keyword">return</span><span>;&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>steps&nbsp;-=&nbsp;1;&nbsp;</span></li><li><span>}&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>searchCell(maze.start)&nbsp;</span></li></ol></pre>
<p><code>steps</code>很好地说明了运行时覆写的原理&mdash;&mdash;当搜索一个未访问的<code>cell</code>时，把它加1，表示 &ldquo;走一步&rdquo;；而回溯的时候，则把它减1，表示&ldquo;退回&rdquo;。这样，如果你搜索地图无果，那么<code>steps</code>还是0。    <br />
<code>steps</code> explained the mechanism of runtime overwriting  well -- when searching one unvisited cell, increase it, means &quot;one  step&quot;; when backtracking, decrease it, means &quot;go back&quot;. Therefore, if  the way does not exist,  <code>steps</code> equals to 0.</p>
<p>运行时覆写的基本思路就是&mdash;&mdash;当进入方法，修改某个东西；当退出方法，则把它改回来。    <br />
Basic principles of Runtime overwritting is Change something when  enter the method, and change it back when exit.</p>
<h4><code>priv</code></h4>
<p>你肯定很好奇调用<code>priv</code>的时候是怎么知道要取那个对象的保护成员的。要知道我们压根没有给<code>priv</code>传<code>this</code>指 针。实际上，<code>priv</code>取的是一个叫<code>bound</code>的对象的保护成员&mdash;&mdash;<code>bound</code>则 是在调用对象方法的时候覆写成传入那个方法的this指针的。    <br />
You will be curious about how <code>priv</code> knows which  object's protected members will be accessed. We never pass  <code>this</code> pointer to <code>priv</code>. Actually, <code>priv</code>  accesses the protected members of an object named &quot;<code>bound</code>&quot;.  &quot;<code>bound</code>&quot; is overrited to<code> this</code> pointer when  invoking a method.</p>
<p>emop中，每个类定义的方法都被包裹，秘密在<code>wrapProtected</code>中。它的代码是：</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;bound;&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="comment">//&nbsp;........</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;wrapProtected&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(method)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;hold&nbsp;=&nbsp;bound;&nbsp;</span></span></li><li class="alt"><span>bound&nbsp;=&nbsp;<span class="keyword">this</span><span>;&nbsp;</span></span></li><li><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;ret&nbsp;=&nbsp;method.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span>bound&nbsp;=&nbsp;hold;&nbsp;</span></li><li><span><span class="keyword">return</span><span>&nbsp;ret;&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span>}&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li><li><span><span class="comment">//&nbsp;........</span><span>&nbsp;</span></span></li><li class="alt"><span>Clz.prototype[each]&nbsp;=&nbsp;wrapProtected(def[each]);&nbsp;</span></li></ol></pre>
<p>因为不能给<code>priv</code>直接传<code>this</code>（否则要他还有何意义），<code>wrapProtected</code>就 做了一个有趣的事情&mdash;&mdash;在对象调用方法之前，把<code>bound</code>设置成传入的<code>this</code>指针，同时做备份； 而当退出时，则把<code>bound</code>再改回来。这么一来二去，<code>method</code>调用时<code><code>priv</code></code>可 以正确找到保护成员，而结束后则像什么都没发生一样。    <br />
Because we can't pass this to <code>priv</code> explicitly, <code>wrapProtected</code>  did something interesting. Before the &quot;real&quot;  <code>method</code>'s invocation, change <code>bound</code> to passed <code>this</code>  pointer, also backup it; After the  <code>method</code> invoked, change <code>bound</code> back. With this  process, when the &quot;real&quot;  <code>method</code> is running, <code>priv</code> works correctly, and,  when it ended, it seems nothing happened to  <code>priv</code> and <code>bound</code>.</p>
<p><code>try ... finally</code>保证了即使<code>method</code>发生异常，<code>bound</code>也 能改回来。当然，这会造成一点性能损失。    <br />
<code>try ... finally</code> ensured that even <code>method</code>  throws an exception,  <code>bound</code> will be changed back. Obviously, it will slow down  the progeam a little.</p>
<p><code>Class.base</code>和<code>Class.attach</code>的原理相似，这里就不深究了。各位可以看代 码研究。    <br />
<code>Class.base</code> and <code>Class.attach</code> works in the  same mechanism. You can read the code above.</p>
<h4><code>base</code></h4>
<p><code>base</code>中使用的技术最为复杂&mdash;&mdash;因为这次覆写的就是它自己。<code>this.base</code>在它自己调 用时，基类方法调用前覆写，基类方法调用后改回。    <br />
Techniques used in <code>base </code>is the most complicated,  becaust it will overwrite itself.  <code>this.base </code>overwrites itself after it is invoked, and before  base method's invocation; and change it back after base method exits.</p>
<p>base搜索基方法依赖在类上维护的baseConstructor属性，它直接指向基类。用于覆写的base由一个叫mgBaseGen的函数生 成，代码是：    <br />
base's searching depends on the baseConstructor property of  classes, which points to it's class. bases used to overwrite is  generated by function mgBaseGen:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;mgBaseGen&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(bcl,&nbsp;original)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">function</span><span>(nname)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;c&nbsp;=&nbsp;bcl,&nbsp;rv;&nbsp;</span></span></li><li><span><span class="keyword">while</span><span>&nbsp;(c&nbsp;&amp;&amp;&nbsp;!c.prototype.hasOwnProperty(nname))&nbsp;c&nbsp;=&nbsp;c.baseConstructor;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(!c)&nbsp;</span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'Cannot&nbsp;find&nbsp;base&nbsp;class&nbsp;with&nbsp;specific&nbsp;method'</span><span>);&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;mgBaseGen(c.baseConstructor,&nbsp;</span><span class="keyword">this</span><span>.base);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li><span>rv&nbsp;=&nbsp;c.prototype[nname].apply(<span class="keyword">this</span><span>,&nbsp;Array.prototype.slice.call(arguments,&nbsp;1));&nbsp;</span></span></li><li class="alt"><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;original;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">return</span><span>&nbsp;rv;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>};&nbsp;</span></li></ol></pre>
<p><code>mgBaseGen</code>接受两个参数，一个是搜索方法的起点<code>bcl</code>，另一个是备份<code>original</code>。 在3-5行，沿着<code>baseConstructor</code>链搜索某个合适的类<code>c</code>，包含<code>nname</code>指 定的方法；接着，把<code>this.base</code>覆写成以<code>c</code>的基类为起点的新<code>base</code>。 然后，调用基类方法。调用完毕，则把<code>this.base</code>改回<code>original</code>，清除痕迹；最后，返 回值。    <br />
<code>mgBaseGen </code>accepts two parameters, ont is the  searching start,  <code>bcl</code>, the other is the backup, <code>original</code>. In  line 3-5, generated  <code>base </code>method searches the class <code>c</code> defines  specified method method; then overwrite the  <code>this.base </code>method by a new <code>base </code>with <code>c.baseConstructor</code>  as searching start. Then, invoke the found base method and change  <code>this.base</code> back.</p>
<p>这样，<code>this.base</code>就以一种神奇的方式工作&mdash;&mdash;如果基类方法还要调用更&ldquo;基类&rdquo;的方法的话，<code>this.base</code>就 会站在更深的地方搜索方法。而当基类方法调用完成时，<code>this.base</code>就像没改过一样。    <br />
In this way, <code>this.base</code> works magically --&nbsp; if the  base method needs to invoke a &quot;baser&quot; method,  <code>this.base</code> will start searching the method at a &quot;deeper&quot;  place. But when the base method is exited,  <code>this.base</code> looks unchanged.</p>
<p><code>this.base</code>加入到原型中使用下面的代码&mdash;&mdash;这几乎不用解释：    <br />
Adding <code>this.base</code> into prototype uses following code  -- explaining is needless:</p>
<pre><ol class="dp-c"><li class="alt"><span><span>Clz.prototype.base&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(name)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;c&nbsp;=&nbsp;Clz.baseConstructor,&nbsp;rv,&nbsp;cler&nbsp;=&nbsp;arguments.callee.caller.caller;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;original&nbsp;=&nbsp;</span><span class="keyword">this</span><span>.base;&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;mgBaseGen(c,&nbsp;original);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li><span>rv&nbsp;=&nbsp;<span class="keyword">this</span><span>.base.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li class="alt"><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;original;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="keyword">return</span><span>&nbsp;rv;&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li></ol></pre>
<h3>类定义的实现    <br />
Implementation of class definition</h3>
<p>在类定义中我们用&ldquo;<code>this.method = function(){...}</code>&rdquo;定义方法，但是，这种定义法是如何变 成一个构造器的呢？事实上在<code>Class</code>中，我们把定义给<code>new</code>了一次：    <br />
In class definitions, we use &quot;<code>this.method = function(){...}</code>&quot;  to define methods. But how did the class definition come into a  constructor. In fact, we constructed the definition once in  <code>Class</code>:</p>
<pre><ol class="dp-c"><li class="alt"><span><span>Class&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(definition,&nbsp;proto)&nbsp;{&nbsp;</span></span></li><li><span><span class="comment">//&nbsp;...</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;ctor,&nbsp;def&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Definition(priv);&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(def.initalize&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>ctor&nbsp;=&nbsp;wrapProtected(def.initalize);&nbsp;</span></li><li><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span>ctor&nbsp;=&nbsp;NULLFUNC;&nbsp;</span></li><li><span>};&nbsp;</span></li><li class="alt"><span><span class="keyword">delete</span><span>&nbsp;def.initalize;&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="comment">//&nbsp;create&nbsp;class</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;Clz&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li class="alt"><span>registerProtecteds(<span class="keyword">this</span><span>);&nbsp;</span></span></li><li><span><span class="keyword">return</span><span>&nbsp;ctor.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span><span class="comment">//&nbsp;...</span><span>&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li></ol></pre>
<p><code>def</code>对象是&ldquo;<code>new</code>&rdquo;定义的产物，接着，如果它包含<code>initalize</code>方 法，则把包裹它作为&ldquo;初始化器&rdquo;，否则，就用空函数。生成的构造器<code>Clz</code>实际上包含了两步，一个是注册保护成员（见下一节）， 另一个则是执行初始器。    <br />
The <code>def </code>object is the result of constructing  definition, and then, if  <code>def</code> contains <code>initalize</code> method, wrap it by <code>wrapProtected </code>and set the initalizer (<code>ctor</code>) to it; if not, set it  to the empty function. Generated constructor <code>Clz</code> contains 2 steps: registering protected menber (see the  selection below), and executing  <code>ctor</code>.</p>
<p>原型的绑定在下一步：    <br />
Prototype is bound in the next:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="comment">//bind&nbsp;prototype</span><span>&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(proto&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function&nbsp;||&nbsp;NClassBase&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(proto&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li><span>Clz.prototype&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;proto;&nbsp;</span></span></li><li class="alt"><span>Clz.baseConstructor&nbsp;=&nbsp;proto;&nbsp;</span></li><li><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(NClassBase&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Function)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>Clz.prototype&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;NClassBase;&nbsp;</span></span></li><li><span>Clz.baseConstructor&nbsp;=&nbsp;NClassBase;&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span>Clz.prototype.base&nbsp;=&nbsp;<span class="keyword">function</span><span>(name)&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;c&nbsp;=&nbsp;Clz.baseConstructor,&nbsp;rv,&nbsp;cler&nbsp;=&nbsp;arguments.callee.caller.caller;&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;original&nbsp;=&nbsp;</span><span class="keyword">this</span><span>.base;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;mgBaseGen(c,&nbsp;original);&nbsp;</span></span></li><li><span><span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span>rv&nbsp;=&nbsp;<span class="keyword">this</span><span>.base.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li><span>}&nbsp;<span class="keyword">finally</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span><span class="keyword">this</span><span>.base&nbsp;=&nbsp;original;&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;rv;&nbsp;</span></span></li><li><span>};&nbsp;</span></li><li class="alt"><span>}&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(proto)&nbsp;Clz.prototype&nbsp;=&nbsp;proto;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">else</span><span>&nbsp;Clz.prototype&nbsp;=&nbsp;{};&nbsp;</span></span></li><li><span>Clz.baseConstructor&nbsp;=&nbsp;Object;&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>proto&nbsp;=&nbsp;Clz.prototype;&nbsp;</span></li></ol></pre>
<p>这里检查了两处，一个是显式传入的<code>proto</code>，另一个是用<code>Class.base</code>注册的基类<code>NClassBase</code>。 如果<code>proto</code>是函数，则构造一个对象做原型，<code>NClassBase</code>同理。如果<code>proto</code>是 一个对象，则把<code>Clz</code>的原型直接赋予它。    <br />
We checked explicitly passed argument <code>proto </code>and <code>NClassBase </code>registered by <code>Class.base</code>. If proto is a function,  the prototype of  <code>Clz </code>will be the object constructed by <code>proto</code>. <code>NClassBase </code>is processed in like manner. If <code>proto </code>is an object,  but not  a function, then directly set<code> Clz.prototype</code> to it.</p>
<h3>保护成员的实现    <br />
Implementation of protected members</h3>
<p>现在我们要深入<code>priv</code>，了解保护成员是如何实现的。    <br />
Now we will see the detail of <code>priv</code>, to know how  protected members implemented.</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;priv&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(n,&nbsp;v)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(!bound.hasOwnProperty(</span><span class="string">'__protected'</span><span>))&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'access&nbsp;denied'</span><span>);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(arguments.length&nbsp;&gt;&nbsp;1)&nbsp;</span><span class="keyword">return</span><span>&nbsp;bound.__protected(CHECK,&nbsp;n,&nbsp;v);&nbsp;</span></span></li><li><span><span class="keyword">else</span><span>&nbsp;</span><span class="keyword">return</span><span>&nbsp;bound.__protected(CHECK,&nbsp;n);&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li></ol></pre>
<p><code>priv</code>的实现异常简单&mdash;&mdash;它调用&hellip;&hellip;对象的<code>__protected</code>方法。等等，这个方法会不会把 保护成员泄密？实际上不会，因为有<code>CHECK</code>。<code>CHECK</code>是一个围在闭包里的&ldquo;令牌&rdquo;，外界几乎无 法获取。<code>__protected</code>方法是在这里注册的：    <br />
The implementation of <code>priv</code> looks very simple. It  invokes ...... the<code> __protected</code> method of the object. But  will this method betray its protected methods? Actually no, because  there is a check. The constant  <code>CHECK </code>is an token object contained in the outer closure and  it's unaccessable outside.<code> __protected</code> was registered  here:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="comment">//&nbsp;Token</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;CHECK&nbsp;=&nbsp;{};&nbsp;</span></span></li><li class="alt"><span><span class="comment">//&nbsp;Empty&nbsp;function</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;NULLFUNC&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{};&nbsp;</span></span></li><li class="alt"><span><span class="comment">//&nbsp;hasOwnProperty&nbsp;checker</span><span>&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;HOPCHECKER&nbsp;=&nbsp;{};&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;registerProtecteds&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(o)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">var</span><span>&nbsp;protecteds&nbsp;=&nbsp;[];&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;p&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(checker,&nbsp;name,&nbsp;value)&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">if</span><span>&nbsp;(checker&nbsp;!==&nbsp;CHECK)&nbsp;</span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'access&nbsp;denied'</span><span>);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(arguments.length&nbsp;&gt;&nbsp;2)&nbsp;</span><span class="keyword">return</span><span>&nbsp;protecteds[name]&nbsp;=&nbsp;value;&nbsp;</span></span></li><li><span><span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(HOPCHECKER.hasOwnProperty.call(protecteds,&nbsp;name))&nbsp;</span><span class="keyword">return</span><span>&nbsp;protecteds[name];&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>p.length&nbsp;=&nbsp;0;&nbsp;</span></li><li class="alt"><span>p.toString&nbsp;=&nbsp;<span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">'access&nbsp;denied'</span><span>)&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>o.__protected&nbsp;=&nbsp;p;&nbsp;</span></li><li><span>};&nbsp;</span></li></ol></pre>
<p>函数<code>p</code>的第一行干的就是检查<code>CHECK</code>，如果&ldquo;令牌&rdquo;不对，对不起，access  denied。接下来的内容就很简单了，基本的hash操作。这里使用了一个小技巧，用<code>HOPCHECKER</code>的<code>hasOwnProperty</code>检 查<code>protecteds</code>的属性有无，防止覆写<code>hasOwnProperty</code>造成检测的错误。    <br />
What the first line of function <code>p</code> did is checking <code>CHECK</code>.  if the token is wrong, then throw an access denied exception. Following  contents are easy, basic hashtable operations.There is a small  technique:&nbsp; checking property existance of protecteds by  <code>HOPCHECKER</code>'s <code>hasOwnProperty</code>, in order to avoid  mistakes made by overwriting  <code>hasOwnProperty</code>.</p>
<p>那么，<code>registerProtecteds</code>是何时&ldquo;注册&rdquo;到对象上的呢？答案在这里：    <br />
So, when does <code>registerProtecteds </code>&quot;registers&quot; to the  object? The answer is here:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;Clz&nbsp;=&nbsp;</span><span class="keyword">function</span><span>()&nbsp;{&nbsp;</span></span></li><li><span>registerProtecteds(<span class="keyword">this</span><span>);&nbsp;</span></span></li><li class="alt"><span><span class="keyword">return</span><span>&nbsp;ctor.apply(</span><span class="keyword">this</span><span>,&nbsp;arguments);&nbsp;</span></span></li><li><span>};&nbsp;</span></li></ol></pre>
<h2>优势    <br />
Advantages</h2>
<ul>
    <li>仍可以使用原生的<code>Clz.prototype.method = function(){}</code>定义方法      <br />
    Native <code>Clz.prototype.method = function(){...}</code> is  still avliable</li>
    <li><code>base</code>在不用<code>Class</code>定义的派生类中仍可使用，只需维护<code>baseConstructor       </code>      <br />
    <code>base </code>is still avaliable in derived classes not  defined by Class, only keeping    <code>baseConstructor </code>needed.</li>
    <li>支持嵌套类      <br />
    Nested classes supported</li>
</ul>
<h2>待改进    <br />
To do</h2>
<ul>
    <li>使用<code>try ... finally</code>造成调试不便      <br />
    <code>try ... finally </code>will make debugging unconvient</li>
    <li>性能损失      <br />
    Preformance lack</li>
    <li>不支持ECMA v5定义的读写器，稍加修改即可<br />
    Accessor defined in ECMA v5 is not supported, but it can be supported  after a little modification.</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/how_to_test_flash_plugin_setup.aspx]]></link>
	<title><![CDATA[如何判断客户端是否安装Flash脚本]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-30 14:00:22</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/how_to_test_flash_plugin_setup.aspx]]></guid>
	<description><![CDATA[<p>某人问我，这里写下。</p>
<p>基本方法如下：</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">typeof</span><span>&nbsp;navigator.plugins&nbsp;!=</span><span class="string">&quot;undefined&quot;</span><span>&nbsp;&amp;&amp;&nbsp;</span><span class="keyword">typeof</span><span>&nbsp;navigator.plugins[</span><span class="string">&quot;Shockwave&nbsp;Flash&quot;</span><span>]&nbsp;==&nbsp;</span><span class="string">&quot;object&quot;</span><span>)&nbsp;{&nbsp;</span></span></li><li><span><span class="comment">//非IE&nbsp;已安装Flash</span><span>&nbsp;</span></span></li><li class="alt"><span>}<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">typeof</span><span>&nbsp;window.ActiveXObject&nbsp;!=&nbsp;</span><span class="string">&quot;undefined&quot;</span><span>)&nbsp;{&nbsp;</span></span></li><li><span><span class="comment">//IE&nbsp;&nbsp;&nbsp;已安装Flash</span><span>&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li></ol></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/yslow_score_calc.aspx]]></link>
	<title><![CDATA[YSlow计算公式]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-25 11:54:29</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/yslow_score_calc.aspx]]></guid>
	<description><![CDATA[<pre class="code">
F = 8&times;{100-[4&times;(JS文件数-3)+4&times;(CSS文件数-2)+3&times;(CSS背景图连接数-6) ] }
	+6&times;(100-10&times;未使用CDN的连接个数)
	+10&times;[100-11&times;(Expire时间小于172800秒的连接个数) ]
	+8&times;[100-11&times;(文件大小大于500字节且 未使用gzip的连接个数)]
	+4&times;[body中没有CSS连接 ? 100∶ (99-10&times;body中的CSS连接数) ]
	+4&times;(100-5&times;head中的JavaScript连接数)
	+3&times;[不存在CSS表达式 ?100: (90-2&times;CSS表达式数目) ]
	+3&times;[100-5&times;(域名数-4)]
	+4&times;(100-10&times;未精简的CSS与JS个数)
	+4&times;(100-10&times;Redirect个数)
	+4&times;[100-5&times;(重复的JavaScript个数+重复的CSS个数) ]
	+2&times;(100-11&times;未使用Etag的连接个数)
	+4&times;(100-5&times;未缓存或者缓存时间不足3600秒的AJAX请求个数)
	+3&times;(100-5&times;请求方式不是GET的AJAX个数)
	+3&times;{DOM元素数量&lt;MaxDOM ?100∶ [99-10&times;&lceil;((DOM元素数量-900))/250&rceil; ] }
	+4&times;(100-5&times;状态为404的连接个数)
	+3&times;[cookie大小不超过1000字节 ?100∶ (99-10&times;&lfloor;页面cookie的大小/1000&rfloor; ) ]
	+3&times;(100-5&times;不满足cookie free要求的链接个数)
	+4&times;[100-(2&times;使用hack的filter个数+5&times;未使用hack的filter个数) ]
	+3&times;(100-5&times;在HTML代码中设定width和height的图片数)
	+2&times;[100-(favicon不可缓存或缓存时间小于3600秒 ? 5∶0)-(favicon大小超过2000字节? 5∶0)]

Score = F / 89
</pre>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/html_vertical_align.aspx]]></link>
	<title><![CDATA[每日一Tip_HTML元素经典垂直居中问题]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-24 10:06:34</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/html_vertical_align.aspx]]></guid>
	<description><![CDATA[<blockquote>
<p><font class="Apple-style-span" face="'Times New Roman'"><span style="font-size: medium; ">经典的垂直问题中，img 的父容器如果 float 了，那么其 display table-cell 将失效，table-cell 只能在 display static 的时候有效，因此解决方案是给 img 再加个包装容器，原来的父容器 float，包装器 table-cell</span></font></p>
</blockquote>
<p>--------来自团队总结</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/js_settimeout_setinterval_experience.aspx]]></link>
	<title><![CDATA[每日一Tip_JS的setTimeout和 setInterval]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-24 9:46:58</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/js_settimeout_setinterval_experience.aspx]]></guid>
	<description><![CDATA[<p>&nbsp;</p>
<blockquote>
<p>&nbsp;<font style="FONT-SIZE: 10pt" face="新宋体" color="#000000">每日Tip：尽量向&nbsp;setTimeout()&nbsp;和&nbsp;setInterval()传送函数名，而不要传送字串。setTimeout()&nbsp;和&nbsp;setInterval()&nbsp;方法近似于&nbsp;eval。如果传进参数是字符串，则在一段时间之后，会和&nbsp;eval一样执行字符串值，当然其低效率也和&nbsp;eval&nbsp;一样。但这些方法也可以接受函数作为第一个参数。在一段时间后将调用此函数，但此函数可在编译时被解释和优化，也就是说会有更好的性能。</font></p>
</blockquote>
<p>&nbsp;</p>
<p>-------来自团队总结</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/swf_in_html_4_format_comparison.aspx]]></link>
	<title><![CDATA[四种静态SWF页面嵌入方法比较]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-23 17:34:13</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/swf_in_html_4_format_comparison.aspx]]></guid>
	<description><![CDATA[加密内容。]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/XUL.aspx]]></link>
	<title><![CDATA[火星文一则]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-18 13:51:01</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/XUL.aspx]]></guid>
	<description><![CDATA[<p>&nbsp;在FireFox粘贴以下链接：</p>
<p><a href="chrome://browser/content/browser.xul ">chrome://browser/content/browser.xul&nbsp;</a></p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/shared_object_getLocal_data_synchronization.aspx]]></link>
	<title><![CDATA[每日一Tip_关于SharedObject.getLocal()的数据同步问题。]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-17 19:48:57</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/shared_object_getLocal_data_synchronization.aspx]]></guid>
	<description><![CDATA[<blockquote>
<p>&nbsp;</p>
<p>&nbsp;SharedObject.getLocal() 如果要在2个同时运行的应用中实现本地数据同步。则需要将SharedObject变量对象声明为局部变量而非全局变量。</p>
</blockquote>
<p>----来自一次项目的总结</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/hXjBVoUGxwKeRrnwKeoA.aspx]]></link>
	<title><![CDATA[HTML5处理音频说明]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-10 14:04:29</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/hXjBVoUGxwKeRrnwKeoA.aspx]]></guid>
	<description><![CDATA[<p>&nbsp;</p>
<script type="text/javascript" src="http://assets.taobaocdn.com/app/tms/tms-edit-link.js"></script>
<script type="text/javascript" src="http://assets.taobaocdn.com/app/tms/tms-edit-link.js"></script>
<p>https://wiki.mozilla.org/Audio_Data_API</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/pwlKZqSiiiTtWtYsAHVV.aspx]]></link>
	<title><![CDATA[[转]Custom events in JavaScript]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-10 13:01:41</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/pwlKZqSiiiTtWtYsAHVV.aspx]]></guid>
	<description><![CDATA[<p>&nbsp;</p>
<!--{12681974632840}-->
<div class="post-head">
<h1>Custom events in JavaScript</h1>
<p class="byline">Posted at March 9, 2010 09:00 am by Nicholas C. Zakas</p>
<p class="tags">Tags: <a rel="tag" href="http://www.nczonline.net/blog/tag/bom/">BOM</a>, <a rel="tag" href="http://www.nczonline.net/blog/tag/dom/">DOM</a>, <a rel="tag" href="http://www.nczonline.net/blog/tag/events/">Events</a>, <a rel="tag" href="http://www.nczonline.net/blog/tag/javascript/">JavaScript</a></p>
<p class="tags">&nbsp;</p>
<p>Without a doubt, the most often-used paradigm in JavaScript is events. Events are a manifestation of the <a href="http://en.wikipedia.org/wiki/Observer_pattern">observer pattern</a>, a well-defined computer science design pattern for loose coupling. <a href="http://en.wikipedia.org/wiki/Loose_coupling">Loose coupling</a> is incredibly important for creating maintainable, stable codebases. I talk a lot about loose coupling and its importance in my talk, <a href="http://www.slideshare.net/nzakas/scalable-javascript-application-architecture">Scalable JavaScript Application Architecture</a> (<a href="http://developer.yahoo.com/yui/theater/video.php?v=zakas-architecture">video</a>), so I won&rsquo;t talk too much about it here. However, the concept is very important to grasp if you wish to progress as a software engineer.</p>
<h2>Events</h2>
<p>Unless you&rsquo;ve never written any JavaScript before, you&rsquo;ve used events at some point in time (admittedly, if you&rsquo;ve never written JavaScript before, the chances of your reading my blog are probably pretty slim). Put quite simply: the way that you tie behavior to web pages is through events. Events are a way of letting interested parties know that an important moment has occurred in the lifecycle of the application. For instance:</p>
<pre><ol class="dp-c"><li class="alt"><span><span>window.onload&nbsp;=&nbsp;</span><span class="keyword">function</span><span>(){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;Application.init();&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li></ol></pre>
<pre><code><br /></code></pre>
<p>In this example, the <code>load</code> event is the interesting moment. I want to know when the window is fully loaded so that I can initialized the JavaScript application. The <code>onload</code> event handler is the location to where an event handler is assigned. The brilliant part is that <code>window</code> doesn&rsquo;t care what web page is loaded or who is writing the code; it just knows that there&rsquo;s a function to call when <code>load</code> occurs. This is the essence of loose coupling: when parts of an application have very limited knowledge of one another.</p>
<p>The <a href="http://javascript.about.com/od/browserobjectmodel/a/bom01.htm">Browser Object Model</a> (BOM) and <a href="http://www.w3.org/DOM/">Document Object Model</a> (DOM) publish events to allow developers access to the interesting moments of the browser and web page, respectively.</p>
<h2>Custom events</h2>
<p>It&rsquo;s no surprise that most JavaScript libraries rely heavily on custom events since this is a pattern that web developers are familiar with. Every major JavaScript library provides its own events, components to enable easy custom event definition, or both. This makes sense, of course, since libraries want to be loosely-coupled to the execution environment, and therefore, to your code.</p>
<p>There&rsquo;s nothing magic about custom events, though, and there&rsquo;s no need to load an entire library if you&rsquo;d like to experiment with custom events. An object that supports custom events needs to be able to do a small set of things:</p>
<ol>
    <li>Assign an event handler for a particular event.</li>
    <li>Remove an event handler for a particular event.</li>
    <li>Fire an event and call all assigned event handlers.</li>
</ol>
<p>The following implements all of this basic functionality:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="comment">//Copyright&nbsp;(c)&nbsp;2010&nbsp;Nicholas&nbsp;C.&nbsp;Zakas.&nbsp;All&nbsp;rights&nbsp;reserved.</span><span>&nbsp;</span></span></li><li><span><span class="comment">//MIT&nbsp;License</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">function</span><span>&nbsp;EventTarget(){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>._listeners&nbsp;=&nbsp;{};&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>EventTarget.prototype&nbsp;=&nbsp;{&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;constructor:&nbsp;EventTarget,&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;addListener:&nbsp;<span class="keyword">function</span><span>(type,&nbsp;listener){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">typeof</span><span>&nbsp;</span><span class="keyword">this</span><span>._listeners[type]&nbsp;==&nbsp;</span><span class="string">&quot;undefined&quot;</span><span>){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>._listeners[type]&nbsp;=&nbsp;[];&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>._listeners[type].push(listener);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;fire:&nbsp;<span class="keyword">function</span><span>(event){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">typeof</span><span>&nbsp;event&nbsp;==&nbsp;</span><span class="string">&quot;string&quot;</span><span>){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;event&nbsp;=&nbsp;{&nbsp;type:&nbsp;event&nbsp;};&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(!event.target){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;event.target&nbsp;=&nbsp;<span class="keyword">this</span><span>;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(!event.type){&nbsp;&nbsp;</span><span class="comment">//falsy</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Error(</span><span class="string">&quot;Event&nbsp;object&nbsp;missing&nbsp;'type'&nbsp;property.&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">this</span><span>._listeners[event.type]&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Array){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;listeners&nbsp;=&nbsp;</span><span class="keyword">this</span><span>._listeners[event.type];&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">var</span><span>&nbsp;i=0,&nbsp;len=listeners.length;&nbsp;i&nbsp;&lt;&nbsp;len;&nbsp;i++){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listeners[i].call(<span class="keyword">this</span><span>,&nbsp;event);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;removeListener:&nbsp;<span class="keyword">function</span><span>(type,&nbsp;listener){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">this</span><span>._listeners[type]&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;Array){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span>&nbsp;listeners&nbsp;=&nbsp;</span><span class="keyword">this</span><span>._listeners[type];&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">var</span><span>&nbsp;i=0,&nbsp;len=listeners.length;&nbsp;i&nbsp;&lt;&nbsp;len;&nbsp;i++){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(listeners[i]&nbsp;===&nbsp;listener){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listeners.splice(i,&nbsp;1);&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">break</span><span>;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>};&nbsp;</span></li></ol></pre>
<pre><code><br /></code></pre>
<p>The <code>EventTarget</code> type has three methods: <code>addListener()</code>, <code>fire()</code>, and <code>removeListener</code>.</p>
<p>The <code>addListener()</code> uses the private <code>_listeners</code> object to store event handlers for various events. When an event handler is added, the method first checks to see if there&rsquo;s a named property for that event type on the <code>_listeners</code> object, and if not, creates one containing an array. The event handler function is then saved to the array for later.</p>
<p>The <code>fire()</code> method fires an event with a given name. In effect, this method&rsquo;s only job is to execute each event handler for the given event type. The method accepts either an object, in which case it&rsquo;s expected to have a <code>type</code> property, or a string, in which case a new object is created and the string is assigned as the value of <code>type</code>. Next, if the event object doesn&rsquo;t have a <code>target</code> property assigned, it is set to the current instance. This effectively creates an event object similar to the one most are familiar with via the BOM and DOM. Once the event object is created, the <code>_listeners</code> object is checked for event handlers, and if found, they are executed. Note that in order to mimic the BOM/DOM approach, event handlers are executed in the scope of <code>this</code> via the <code>call()</code> method.</p>
<p>The last method, <code>removeListener()</code>, simply reverses the process of <code>addListener()</code>. It searches through the <code>_listeners</code> property for the given event type to locate the specified event handler. If found, the event handler is removed by using the array&rsquo;s <code>splice()</code> method, and otherwise it exits without doing anything.</p>
<p>Basic usage:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;target&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;EventTarget();&nbsp;</span></span></li><li><span><span class="keyword">function</span><span>&nbsp;handleEvent(event){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;alert(event.type);&nbsp;</span></li><li><span>};&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>target.addListener(<span class="string">&quot;foo&quot;</span><span>,&nbsp;handleEvent);&nbsp;</span></span></li><li class="alt"><span>target.fire({&nbsp;type:&nbsp;<span class="string">&quot;foo&quot;</span><span>&nbsp;});&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//can&nbsp;also&nbsp;do&nbsp;target.fire(&quot;foo&quot;)</span><span>&nbsp;</span></span></li><li><span>target.removeListener(<span class="string">&quot;foo&quot;</span><span>,&nbsp;handleEvent);&nbsp;</span></span></li></ol></pre>
<pre><code><br /></code></pre>
<p>Practically speaking, you&rsquo;ll likely not want to use an instance of <code>EventTarget</code> directly, but rather inherit from it:</p>
<pre><ol class="dp-c"><li class="alt"><span><span class="keyword">function</span><span>&nbsp;MyObject(){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;EventTarget.call(<span class="keyword">this</span><span>);&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>MyObject.prototype&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;EventTarget();&nbsp;</span></span></li><li><span>MyObject.prototype.constructor&nbsp;=&nbsp;MyObject;&nbsp;</span></li><li class="alt"><span>MyObject.prototype.foo&nbsp;=&nbsp;<span class="keyword">function</span><span>(){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.fire(</span><span class="string">&quot;foo&quot;</span><span>);&nbsp;</span></span></li><li class="alt"><span>};&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">var</span><span>&nbsp;o&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;MyObject();&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span>o.addListener(<span class="string">&quot;foo&quot;</span><span>,&nbsp;</span><span class="keyword">function</span><span>(){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;alert(<span class="string">&quot;Foo&nbsp;just&nbsp;happened.&quot;</span><span>);&nbsp;</span></span></li><li class="alt"><span>});&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>o.foo();&nbsp;</span></li></ol></pre>
<pre><code><br /></code></pre>
<p>Typically, events are fired in reaction to some other method call, as in this example (events are usually not fired external to the object that is publishing the events).</p>
<h2>What about&hellip;?</h2>
<p>This is a pretty barebones implementation of a custom event providing object, so inevitably someone will come along and ask why I didn&rsquo;t include one feature or another. There are, of course, a lot of enhancements you can make to custom events if you so desire. Some enhancements others have implemented:</p>
<ul>
    <li>Bubbling of events</li>
    <li>Continue to execute event handlers even if one throws an error</li>
    <li>Allow event handlers to cancel further processing or default actions</li>
</ul>
<p>Each of these can be built pretty easily on top of the base presented in this post.</p>
<h2>Conclusion</h2>
<p>Custom events are a very powerful and useful pattern in JavaScript programming, and your usage of them doesn&rsquo;t have to rely on a large JavaScript library. Implementing your own custom events is easy. The implementation presented in this post is a minimum feature set that typically fulfills most requirements, but you can consider it as a starting point for more advanced functionality if your requirements are more complex.</p>
</div>
<!--{12681974632841}-->
<script type="text/javascript" src="http://assets.taobaocdn.com/app/tms/tms-edit-link.js"></script>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/recommendation_algorithm.aspx]]></link>
	<title><![CDATA[阅读摘要：推荐算法介绍(隐性打分)]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-3-1 19:40:59</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/recommendation_algorithm.aspx]]></guid>
	<description><![CDATA[<p><span style="color: rgb(192, 192, 192); ">&nbsp;来源:</span><a href="http://blog.csdn.net/liuzhenwen/archive/2009/04/22/4101003.aspx"><span style="color: rgb(192, 192, 192); ">http://blog.csdn.net/liuzhenwen/archive/2009/04/22/4101003.aspx</span></a></p>
<p>推荐系统最早在<a target="_blank" style="text-decoration: none; color: rgb(51, 102, 153); " href="http://www.amazon.com/"><span style="line-height: 21px; text-decoration: underline; "><span style="line-height: 21px; color: rgb(0, 0, 255); ">亚马逊</span></span></a>的网站上应用，根据以往用户的购买行为，推荐出购买某种产品同时可能购买的其他产品。</p>
<blockquote>
<p><span style="background-color: rgb(255, 255, 153); ">直接打分需要用户的参与程度比较高，很多网站都在内容页中留一个打分的按钮，从1～5选一 个，我可能喜欢这篇文章，可我哪里知道我喜欢的程度是几分啊，还要我去思考，而网站设计中一条很重要的原则是:Do not let me think!，于是我就胡打一个分数或者不打，而隐性的打分则不同，只有你喜欢的图书你才会购买，只有你喜欢的歌曲才会听多次。</span></p>
</blockquote>
<p>最近邻搜索算法一般是皮尔森相关系数（<a target="_blank" style="text-decoration: none; color: rgb(51, 102, 153); " href="http://en.wikipedia.org/wiki/Correlation"><span style="line-height: 21px; text-decoration: underline; "><span style="line-height: 21px; color: rgb(129, 0, 129); ">Person Correlation Coefficient</span></span></a>）、余弦相似性（<a target="_blank" style="text-decoration: none; color: rgb(51, 102, 153); " href="http://www10.org/cdrom/papers/519/node12.html"><span style="line-height: 21px; text-decoration: underline; "><span style="line-height: 21px; color: rgb(0, 0, 255); ">Cosine-based Similarity</span></span></a>）以及调整余弦相似性（<a target="_blank" style="text-decoration: none; color: rgb(51, 102, 153); " href="http://www10.org/cdrom/papers/519/node14.html"><span style="line-height: 21px; text-decoration: underline; "><span style="line-height: 21px; color: rgb(0, 0, 255); ">Adjusted Cosine Similarity</span></span></a>）。关于余弦定理在数据挖掘中的应用，google黑白报有过介绍，可以参考<span style="line-height: 21px; text-decoration: underline; "><span style="line-height: 21px; color: rgb(129, 0, 129); "><a target="_blank" style="text-decoration: none; color: rgb(51, 102, 153); " href="http://www.googlechinablog.com/2006/07/12.html">数学之美 系列 12 - 余弦定理和新闻的分类</a>。</span></span></p>
<p>&nbsp;</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; "><strong>基本原理</strong></p>
<blockquote style="border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dotted; border-right-style: dotted; border-bottom-style: dotted; border-left-style: dotted; border-top-color: rgb(152, 164, 127); border-right-color: rgb(152, 164, 127); border-bottom-color: rgb(152, 164, 127); border-left-color: rgb(152, 164, 127); background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(245, 245, 245); font: normal normal normal 12px/normal simsun; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; background-position: initial initial; background-repeat: initial initial; ">
<table border="0" style="width: 300px; height: 184px; ">
    <tbody>
        <tr>
            <td><strong>用户&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td>
            <td><strong>对事物A打分</strong></td>
            <td><strong>对事物B打分</strong></td>
        </tr>
        <tr>
            <td><strong>X</strong></td>
            <td><strong>3</strong></td>
            <td><strong>4</strong></td>
        </tr>
        <tr>
            <td><strong>Y</strong></td>
            <td><strong>2</strong></td>
            <td><strong>4</strong></td>
        </tr>
        <tr>
            <td><strong>Z</strong></td>
            <td><strong>4</strong></td>
            <td><strong>?</strong></td>
        </tr>
    </tbody>
</table>
</blockquote>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; ">用户Z对事物B的打分可能是多少呢？股票上有个说法是平均值可以掩盖一切异常波动，所以股票上的各个技术指标收拾不同时间段的平均值的曲线图或者柱 状图等。同样的，Slope one算法也认为：平均值也可以代替某两个未知个体之间的打分差异，事物A对事物B的平均很差是：((3 - 4) + (2 - 4)) / 2 = -1.5，也就是说人们对事物B的打分一般比事物A的打分要高1.5，于是Slope one算法就猜测Z对事物B的打分是4 + 1.5 = 5.5</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; ">&nbsp;</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; ">&nbsp;</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; "><strong>加权算法</strong></p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; ">有n个人对事物A和事物B打分了，R(A-&gt;B)表示这n个人对A和对B打分的平均差（A-B）,有m个人对事物B和事物C打分 了，R（C-&gt;B）表示这m个人对C和对B打分的平均差（C-B），注意都是平均差而不是平方差，现在某个用户对A的打分是ra，对C的打分是 rc，那么A对B的打分可能是：</p>
<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; "><strong>rb = (n * (ra - R(A-&gt;B)) + m * (rc&nbsp;- R(C-&gt;B)))/(m+n)</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<pre><ol class="dp-c"><li class="alt">&nbsp;</li><li class="alt"><span><span>#&nbsp;This&nbsp;is&nbsp;the&nbsp;code&nbsp;in&nbsp;plain&nbsp;text&nbsp;out&nbsp;of&nbsp;the&nbsp;technical&nbsp;report.&nbsp;</span></span></li><li><span>#&nbsp;</span></li><li class="alt"><span>#&nbsp;Daniel&nbsp;Lemire,&nbsp;Sean&nbsp;McGrath,&nbsp;Implementing&nbsp;a&nbsp;Rating-Based&nbsp;Item-to-Item&nbsp;</span></li><li><span>#&nbsp;Recommender&nbsp;System&nbsp;in&nbsp;PHP/SQL,&nbsp;Technical&nbsp;Report&nbsp;D-01,&nbsp;January&nbsp;2005.&nbsp;</span></li><li class="alt"><span>#&nbsp;</span></li><li><span>#&nbsp;http:<span class="comment">//www.ondelette.com/lemire/abstracts/TRD01.html</span><span>&nbsp;</span></span></li><li class="alt"><span>#&nbsp;</span></li><li><span>#&nbsp;This&nbsp;code&nbsp;is&nbsp;in&nbsp;the&nbsp;<span class="keyword">public</span><span>&nbsp;domain,&nbsp;</span><span class="keyword">use</span><span>&nbsp;at&nbsp;your&nbsp;own&nbsp;risks.&nbsp;</span></span></li><li class="alt"><span>#&nbsp;It&nbsp;is&nbsp;assumed&nbsp;that&nbsp;you&nbsp;looked&nbsp;at&nbsp;the&nbsp;report&nbsp;<span class="keyword">and</span><span>&nbsp;know&nbsp;some&nbsp;SQL&nbsp;</span><span class="keyword">and</span><span>&nbsp;PHP.&nbsp;</span></span></li><li><span>#&nbsp;</span></li><li class="alt"><span>#&nbsp;Daniel&nbsp;Lemire,&nbsp;February&nbsp;3rd&nbsp;2005&nbsp;</span></li><li><span>#&nbsp;</span></li><li class="alt"><span>#&nbsp;First&nbsp;part&nbsp;is&nbsp;sample&nbsp;SQL&nbsp;code.&nbsp;</span></li><li><span>#########CUT&nbsp;HERE####################&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>CREATE&nbsp;TABLE&nbsp;rating&nbsp;(&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;userID&nbsp;INT&nbsp;PRIMARY&nbsp;KEY,&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;itemID&nbsp;INT&nbsp;NOT&nbsp;NULL,&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ratingValue&nbsp;INT&nbsp;NOT&nbsp;NULL,&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;datetimestamp&nbsp;TIMESTAMP&nbsp;NOT&nbsp;NULL&nbsp;</span></li><li class="alt"><span>);&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>CREATE&nbsp;TABLE&nbsp;dev&nbsp;(&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;itemID1&nbsp;int(11)&nbsp;NOT&nbsp;NULL&nbsp;<span class="keyword">default</span><span>&nbsp;</span><span class="string">'0'</span><span>,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;itemID2&nbsp;int(11)&nbsp;NOT&nbsp;NULL&nbsp;<span class="keyword">default</span><span>&nbsp;</span><span class="string">'0'</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="func">count</span><span>&nbsp;int(11)&nbsp;NOT&nbsp;NULL&nbsp;</span><span class="keyword">default</span><span>&nbsp;</span><span class="string">'0'</span><span>,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;sum&nbsp;int(11)&nbsp;NOT&nbsp;NULL&nbsp;<span class="keyword">default</span><span>&nbsp;</span><span class="string">'0'</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;PRIMARY&nbsp;KEY&nbsp;&nbsp;(itemID1,itemID2)&nbsp;</span></li><li><span>);&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>#&nbsp;simple&nbsp;query&nbsp;to&nbsp;output&nbsp;10&nbsp;most&nbsp;liked&nbsp;items&nbsp;</span></li><li><span>#&nbsp;by&nbsp;people&nbsp;who&nbsp;rated&nbsp;item&nbsp;1&nbsp;</span></li><li class="alt"><span>SELECT&nbsp;itemID2,&nbsp;(&nbsp;sum&nbsp;/&nbsp;<span class="func">count</span><span>&nbsp;)&nbsp;AS&nbsp;average&nbsp;</span></span></li><li><span>FROM&nbsp;dev&nbsp;</span></li><li class="alt"><span>WHERE&nbsp;<span class="func">count</span><span>&nbsp;&gt;&nbsp;2&nbsp;AND&nbsp;itemID1&nbsp;=&nbsp;1&nbsp;</span></span></li><li><span>ORDER&nbsp;&nbsp;BY&nbsp;(&nbsp;sum&nbsp;/&nbsp;<span class="func">count</span><span>&nbsp;)&nbsp;DESC&nbsp;</span></span></li><li class="alt"><span>LIMIT&nbsp;10;&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>#&nbsp;Next&nbsp;part&nbsp;is&nbsp;sample&nbsp;PHP&nbsp;code.&nbsp;</span></li><li><span>#########CUT&nbsp;HERE####################&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="comment">//&nbsp;This&nbsp;code&nbsp;assumes&nbsp;$itemID&nbsp;is&nbsp;set&nbsp;to&nbsp;that&nbsp;of&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="comment">//&nbsp;the&nbsp;item&nbsp;that&nbsp;was&nbsp;just&nbsp;rated.&nbsp;</span><span>&nbsp;</span></span></li><li><span><span class="comment">//&nbsp;Get&nbsp;all&nbsp;of&nbsp;the&nbsp;user's&nbsp;rating&nbsp;pairs</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="vars">$sql</span><span>&nbsp;=&nbsp;&quot;SELECT&nbsp;DISTINCT&nbsp;r.itemID,&nbsp;r2.ratingValue&nbsp;-&nbsp;r.ratingValue&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">as</span><span>&nbsp;rating_difference&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM&nbsp;rating&nbsp;r,&nbsp;rating&nbsp;r2&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE&nbsp;r.userID=<span class="vars">$userID</span><span>&nbsp;AND&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r2.itemID=<span class="vars">$itemID</span><span>&nbsp;AND&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r2.userID=<span class="vars">$userID</span><span>;&quot;;&nbsp;</span></span></li><li class="alt"><span><span class="vars">$db_result</span><span>&nbsp;=&nbsp;mysql_query(</span><span class="vars">$sql</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;</span></span></li><li><span><span class="vars">$num_rows</span><span>&nbsp;=&nbsp;mysql_num_rows(</span><span class="vars">$db_result</span><span>);&nbsp;</span></span></li><li class="alt"><span><span class="comment">//For&nbsp;every&nbsp;one&nbsp;of&nbsp;the&nbsp;user's&nbsp;rating&nbsp;pairs,&nbsp;</span><span>&nbsp;</span></span></li><li><span><span class="comment">//update&nbsp;the&nbsp;dev&nbsp;table</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="keyword">while</span><span>&nbsp;(</span><span class="vars">$row</span><span>&nbsp;=&nbsp;mysql_fetch_assoc(</span><span class="vars">$db_result</span><span>))&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$other_itemID</span><span>&nbsp;=&nbsp;</span><span class="vars">$row</span><span>[</span><span class="string">&quot;itemID&quot;</span><span>];&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$rating_difference</span><span>&nbsp;=&nbsp;</span><span class="vars">$row</span><span>[</span><span class="string">&quot;rating_difference&quot;</span><span>];&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//if&nbsp;the&nbsp;pair&nbsp;($itemID,&nbsp;$other_itemID)&nbsp;is&nbsp;already&nbsp;in&nbsp;the&nbsp;dev&nbsp;table</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//then&nbsp;we&nbsp;want&nbsp;to&nbsp;update&nbsp;2&nbsp;rows.</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(mysql_num_rows(mysql_query(&quot;SELECT&nbsp;itemID1&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;FROM&nbsp;dev&nbsp;WHERE&nbsp;itemID1=<span class="vars">$itemID</span><span>&nbsp;AND&nbsp;itemID2=</span><span class="vars">$other_itemID</span><span>&quot;,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$connection</span><span>))&nbsp;&gt;&nbsp;0)&nbsp;&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sql</span><span>&nbsp;=&nbsp;&quot;UPDATE&nbsp;dev&nbsp;SET&nbsp;</span><span class="func">count</span><span>=</span><span class="func">count</span><span>+1,&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;sum=sum+<span class="vars">$rating_difference</span><span>&nbsp;WHERE&nbsp;itemID1=</span><span class="vars">$itemID</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;AND&nbsp;itemID2=<span class="vars">$other_itemID</span><span>&quot;;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysql_query(<span class="vars">$sql</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//We&nbsp;only&nbsp;want&nbsp;to&nbsp;update&nbsp;if&nbsp;the&nbsp;items&nbsp;are&nbsp;different&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$itemID</span><span>&nbsp;!=&nbsp;</span><span class="vars">$other_itemID</span><span>)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sql</span><span>&nbsp;=&nbsp;&quot;UPDATE&nbsp;dev&nbsp;SET&nbsp;</span><span class="func">count</span><span>=</span><span class="func">count</span><span>+1,&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum=sum-<span class="vars">$rating_difference</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE&nbsp;(itemID1=<span class="vars">$other_itemID</span><span>&nbsp;AND&nbsp;itemID2=</span><span class="vars">$itemID</span><span>)&quot;;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysql_query(<span class="vars">$sql</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;{&nbsp;</span><span class="comment">//we&nbsp;want&nbsp;to&nbsp;insert&nbsp;2&nbsp;rows&nbsp;into&nbsp;the&nbsp;dev&nbsp;table</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sql</span><span>&nbsp;=&nbsp;&quot;INSERT&nbsp;INTO&nbsp;dev&nbsp;VALUES&nbsp;(</span><span class="vars">$itemID</span><span>,&nbsp;</span><span class="vars">$other_itemID</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1,&nbsp;<span class="vars">$rating_difference</span><span>)&quot;;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysql_query(<span class="vars">$sql</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//We&nbsp;only&nbsp;want&nbsp;to&nbsp;insert&nbsp;if&nbsp;the&nbsp;items&nbsp;are&nbsp;different&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$itemID</span><span>&nbsp;!=&nbsp;</span><span class="vars">$other_itemID</span><span>)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sql</span><span>&nbsp;=&nbsp;&quot;INSERT&nbsp;INTO&nbsp;dev&nbsp;VALUES&nbsp;(</span><span class="vars">$other_itemID</span><span>,&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$itemID</span><span>,&nbsp;1,&nbsp;-</span><span class="vars">$rating_difference</span><span>)&quot;;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysql_query(<span class="vars">$sql</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>}&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">function</span><span>&nbsp;predict(</span><span class="vars">$userID</span><span>,&nbsp;</span><span class="vars">$itemID</span><span>)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">global</span><span>&nbsp;</span><span class="vars">$connection</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$denom</span><span>&nbsp;=&nbsp;0.0;&nbsp;</span><span class="comment">//denominator</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$numer</span><span>&nbsp;=&nbsp;0.0;&nbsp;</span><span class="comment">//numerator&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$k</span><span>&nbsp;=&nbsp;</span><span class="vars">$itemID</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sql</span><span>&nbsp;=&nbsp;&quot;SELECT&nbsp;r.itemID,&nbsp;r.ratingValue&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;FROM&nbsp;rating&nbsp;r&nbsp;WHERE&nbsp;r.userID=<span class="vars">$userID</span><span>&nbsp;AND&nbsp;r.itemID&nbsp;&lt;&gt;&nbsp;</span><span class="vars">$itemID</span><span>&quot;;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$db_result</span><span>&nbsp;=&nbsp;mysql_query(</span><span class="vars">$sql</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//for&nbsp;all&nbsp;items&nbsp;the&nbsp;user&nbsp;has&nbsp;rated</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>&nbsp;(</span><span class="vars">$row</span><span>&nbsp;=&nbsp;mysql_fetch_assoc(</span><span class="vars">$db_result</span><span>))&nbsp;&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$j</span><span>&nbsp;=&nbsp;</span><span class="vars">$row</span><span>[</span><span class="string">&quot;itemID&quot;</span><span>];&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$ratingValue</span><span>&nbsp;=&nbsp;</span><span class="vars">$row</span><span>[</span><span class="string">&quot;ratingValue&quot;</span><span>];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//get&nbsp;the&nbsp;number&nbsp;of&nbsp;times&nbsp;k&nbsp;and&nbsp;j&nbsp;have&nbsp;both&nbsp;been&nbsp;rated&nbsp;by&nbsp;the&nbsp;same&nbsp;user</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sql2</span><span>&nbsp;=&nbsp;</span><span class="string">&quot;SELECT&nbsp;d.count,&nbsp;d.sum&nbsp;FROM&nbsp;dev&nbsp;d&nbsp;WHERE&nbsp;itemID1=$k&nbsp;AND&nbsp;itemID2=$j&quot;</span><span>;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$count_result</span><span>&nbsp;=&nbsp;mysql_query(</span><span class="vars">$sql2</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//skip&nbsp;the&nbsp;calculation&nbsp;if&nbsp;it&nbsp;isn't&nbsp;found</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(mysql_num_rows(</span><span class="vars">$count_result</span><span>)&nbsp;&gt;&nbsp;0)&nbsp;&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$count</span><span>&nbsp;=&nbsp;mysql_result(</span><span class="vars">$count_result</span><span>,&nbsp;0,&nbsp;</span><span class="string">&quot;count&quot;</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sum</span><span>&nbsp;=&nbsp;mysql_result(</span><span class="vars">$count_result</span><span>,&nbsp;0,&nbsp;</span><span class="string">&quot;sum&quot;</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//calculate&nbsp;the&nbsp;average</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$average</span><span>&nbsp;=&nbsp;</span><span class="vars">$sum</span><span>&nbsp;/&nbsp;</span><span class="vars">$count</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//increment&nbsp;denominator&nbsp;by&nbsp;count</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$denom</span><span>&nbsp;+=&nbsp;</span><span class="vars">$count</span><span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//increment&nbsp;the&nbsp;numerator</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$numer</span><span>&nbsp;+=&nbsp;</span><span class="vars">$count</span><span>&nbsp;*&nbsp;(</span><span class="vars">$average</span><span>&nbsp;+&nbsp;</span><span class="vars">$ratingValue</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(</span><span class="vars">$denom</span><span>&nbsp;==&nbsp;0)&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;0;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;(</span><span class="vars">$numer</span><span>&nbsp;/&nbsp;</span><span class="vars">$denom</span><span>);&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">function</span><span>&nbsp;predict_all(</span><span class="vars">$userID</span><span>&nbsp;)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$sql2</span><span>&nbsp;=&nbsp;&quot;SELECT&nbsp;d.itemID1&nbsp;</span><span class="keyword">as</span><span>&nbsp;</span><span class="string">'item'</span><span>,&nbsp;sum(d.</span><span class="func">count</span><span>)&nbsp;</span><span class="keyword">as</span><span>&nbsp;</span><span class="string">'denom'</span><span>,&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;sum(d.sum&nbsp;+&nbsp;d.<span class="func">count</span><span>*r.ratingValue)&nbsp;</span><span class="keyword">as</span><span>&nbsp;</span><span class="string">'numer'</span><span>&nbsp;FROM&nbsp;item&nbsp;i,&nbsp;rating&nbsp;r,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;dev&nbsp;d&nbsp;WHERE&nbsp;r.userID=<span class="vars">$userID</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;AND&nbsp;d.itemID1&lt;&gt;r.itemID&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;AND&nbsp;d.itemID2=r.itemID&nbsp;GROUP&nbsp;BY&nbsp;d.itemID1&quot;;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;mysql_query(</span><span class="vars">$sql2</span><span>,&nbsp;</span><span class="vars">$connection</span><span>);&nbsp;</span></span></li><li><span>}&nbsp;</span></li></ol></pre>
<p>&nbsp;</p>
<p>Java：</p>
<pre><ol class="dp-j"><li class="alt"><span><span class="keyword">import</span><span>&nbsp;java.util.*;&nbsp;</span></span></li><li><span><span class="comment">/**</span>&nbsp;</span></li><li class="alt"><span><span class="comment">*&nbsp;Daniel&nbsp;Lemire</span>&nbsp;</span></li><li><span><span class="comment">*&nbsp;A&nbsp;simple&nbsp;implementation&nbsp;of&nbsp;the&nbsp;weighted&nbsp;slope&nbsp;one</span>&nbsp;</span></li><li class="alt"><span><span class="comment">*&nbsp;algorithm&nbsp;in&nbsp;Java&nbsp;for&nbsp;item-based&nbsp;collaborative&nbsp;</span>&nbsp;</span></li><li><span><span class="comment">*&nbsp;filtering.&nbsp;</span>&nbsp;</span></li><li class="alt"><span><span class="comment">*&nbsp;Assumes&nbsp;Java&nbsp;1.5.</span>&nbsp;</span></li><li><span><span class="comment">*</span>&nbsp;</span></li><li class="alt"><span><span class="comment">*&nbsp;See&nbsp;main&nbsp;function&nbsp;for&nbsp;example.</span>&nbsp;</span></li><li><span><span class="comment">*</span>&nbsp;</span></li><li class="alt"><span><span class="comment">*&nbsp;June&nbsp;1st&nbsp;2006.</span>&nbsp;</span></li><li><span><span class="comment">*&nbsp;Revised&nbsp;by&nbsp;Marco&nbsp;Ponzi&nbsp;on&nbsp;March&nbsp;29th&nbsp;2007</span>&nbsp;</span></li><li class="alt"><span><span class="comment">*/</span><span>&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;SlopeOne&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String&nbsp;args[]){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;this&nbsp;is&nbsp;my&nbsp;data&nbsp;base</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;UserId,Map&lt;ItemId,Float&gt;&gt;&nbsp;data&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;UserId,Map&lt;ItemId,Float&gt;&gt;();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;items</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ItemId&nbsp;item1&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;ItemId(</span><span class="string">&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;candy&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;ItemId&nbsp;item2&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;ItemId(</span><span class="string">&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dog&quot;</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ItemId&nbsp;item3&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;ItemId(</span><span class="string">&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cat&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;ItemId&nbsp;item4&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;ItemId(</span><span class="string">&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;war&quot;</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ItemId&nbsp;item5&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;ItemId(</span><span class="string">&quot;strange&nbsp;food&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;mAllItems&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;ItemId[]{item1,&nbsp;item2,&nbsp;item3,&nbsp;item4,&nbsp;item5};&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//I'm&nbsp;going&nbsp;to&nbsp;fill&nbsp;it&nbsp;in</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;user1&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;user2&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;user3&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;user4&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user1.put(item1,<span class="number">1</span><span>.0f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;user1.put(item2,<span class="number">0</span><span>.5f);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user1.put(item4,<span class="number">0</span><span>.1f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;data.put(<span class="keyword">new</span><span>&nbsp;UserId(</span><span class="string">&quot;Bob&quot;</span><span>),user1);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user2.put(item1,<span class="number">1</span><span>.0f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;user2.put(item3,<span class="number">0</span><span>.5f);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user2.put(item4,<span class="number">0</span><span>.2f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;data.put(<span class="keyword">new</span><span>&nbsp;UserId(</span><span class="string">&quot;Jane&quot;</span><span>),user2);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user3.put(item1,<span class="number">0</span><span>.9f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;user3.put(item2,<span class="number">0</span><span>.4f);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user3.put(item3,<span class="number">0</span><span>.5f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;user3.put(item4,<span class="number">0</span><span>.1f);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;data.put(<span class="keyword">new</span><span>&nbsp;UserId(</span><span class="string">&quot;Jo&quot;</span><span>),user3);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;user4.put(item1,<span class="number">0</span><span>.1f);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//user4.put(item2,0.4f);</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//user4.put(item3,0.5f);</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user4.put(item4,<span class="number">1</span><span>.0f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;user4.put(item5,<span class="number">0</span><span>.4f);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;data.put(<span class="keyword">new</span><span>&nbsp;UserId(</span><span class="string">&quot;StrangeJo&quot;</span><span>),user4);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;next,&nbsp;I&nbsp;create&nbsp;my&nbsp;predictor&nbsp;engine</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;SlopeOne&nbsp;so&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;SlopeOne(data);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="string">&quot;Here's&nbsp;the&nbsp;data&nbsp;I&nbsp;have&nbsp;accumulated...&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;so.printData();&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;then,&nbsp;I'm&nbsp;going&nbsp;to&nbsp;test&nbsp;it&nbsp;out...</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;user&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="string">&quot;Ok,&nbsp;now&nbsp;we&nbsp;predict...&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user.put(item5,<span class="number">0</span><span>.4f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="string">&quot;Inputting...&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;SlopeOne.print(user);&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="string">&quot;Getting...&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;SlopeOne.print(so.predict(user));&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;user.put(item4,<span class="number">0</span><span>.2f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="string">&quot;Inputting...&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;SlopeOne.print(user);&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="string">&quot;Getting...&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;SlopeOne.print(so.predict(user));&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;Map&lt;UserId,Map&lt;ItemId,Float&gt;&gt;&nbsp;mData;&nbsp;</span></li><li><span>&nbsp;&nbsp;Map&lt;ItemId,Map&lt;ItemId,Float&gt;&gt;&nbsp;mDiffMatrix;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;Map&lt;ItemId,Map&lt;ItemId,Integer&gt;&gt;&nbsp;mFreqMatrix;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">static</span><span>&nbsp;ItemId[]&nbsp;mAllItems;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;SlopeOne(Map&lt;UserId,Map&lt;ItemId,Float&gt;&gt;&nbsp;data)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;mData&nbsp;=&nbsp;data;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;buildDiffMatrix();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;*&nbsp;Based&nbsp;on&nbsp;existing&nbsp;data,&nbsp;and&nbsp;using&nbsp;weights,</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;*&nbsp;try&nbsp;to&nbsp;predict&nbsp;all&nbsp;missing&nbsp;ratings.</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;*&nbsp;The&nbsp;trick&nbsp;to&nbsp;make&nbsp;this&nbsp;more&nbsp;scalable&nbsp;is&nbsp;to&nbsp;consider</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;*&nbsp;only&nbsp;mDiffMatrix&nbsp;entries&nbsp;having&nbsp;a&nbsp;large&nbsp;&nbsp;(&gt;1)&nbsp;mFreqMatrix</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;*&nbsp;entry.</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;*</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;*&nbsp;It&nbsp;will&nbsp;output&nbsp;the&nbsp;prediction&nbsp;0&nbsp;when&nbsp;no&nbsp;prediction&nbsp;is&nbsp;possible.</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;*/</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;Map&lt;ItemId,Float&gt;&nbsp;predict(Map&lt;ItemId,Float&gt;&nbsp;user)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;predictions&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Integer&gt;&nbsp;frequencies&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Integer&gt;();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;mDiffMatrix.keySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frequencies.put(j,<span class="number">0</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predictions.put(j,<span class="number">0</span><span>.0f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;user.keySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;k&nbsp;:&nbsp;mDiffMatrix.keySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span><span>&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">float</span><span>&nbsp;newval&nbsp;=&nbsp;(&nbsp;mDiffMatrix.get(k).get(j).floatValue()&nbsp;+&nbsp;user.get(j).floatValue()&nbsp;)&nbsp;*&nbsp;mFreqMatrix.get(k).get(j).intValue();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predictions.put(k,&nbsp;predictions.get(k)+newval);&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frequencies.put(k,&nbsp;frequencies.get(k)+mFreqMatrix.get(k).get(j).intValue());&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">catch</span><span>(NullPointerException&nbsp;e)&nbsp;{}&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;cleanpredictions&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;predictions.keySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(frequencies.get(j)&gt;</span><span class="number">0</span><span>)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cleanpredictions.put(j,&nbsp;predictions.get(j).floatValue()/frequencies.get(j).intValue());&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;user.keySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cleanpredictions.put(j,user.get(j));&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;cleanpredictions;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;*&nbsp;Based&nbsp;on&nbsp;existing&nbsp;data,&nbsp;and&nbsp;not&nbsp;using&nbsp;weights,</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;*&nbsp;try&nbsp;to&nbsp;predict&nbsp;all&nbsp;missing&nbsp;ratings.</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;*&nbsp;The&nbsp;trick&nbsp;to&nbsp;make&nbsp;this&nbsp;more&nbsp;scalable&nbsp;is&nbsp;to&nbsp;consider</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;*&nbsp;only&nbsp;mDiffMatrix&nbsp;entries&nbsp;having&nbsp;a&nbsp;large&nbsp;&nbsp;(&gt;1)&nbsp;mFreqMatrix</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;*&nbsp;entry.</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;*/</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;Map&lt;ItemId,Float&gt;&nbsp;weightlesspredict(Map&lt;ItemId,Float&gt;&nbsp;user)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Float&gt;&nbsp;predictions&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;HashMap&lt;ItemId,Integer&gt;&nbsp;frequencies&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Integer&gt;();&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;mDiffMatrix.keySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predictions.put(j,<span class="number">0</span><span>.0f);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frequencies.put(j,<span class="number">0</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;user.keySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;k&nbsp;:&nbsp;mDiffMatrix.keySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//System.out.println(&quot;Average&nbsp;diff&nbsp;between&nbsp;&quot;+j+&quot;&nbsp;and&nbsp;&quot;+&nbsp;k&nbsp;+&nbsp;&quot;&nbsp;is&nbsp;&quot;+mDiffMatrix.get(k).get(j).floatValue()+&quot;&nbsp;with&nbsp;n&nbsp;=&nbsp;&quot;+mFreqMatrix.get(k).get(j).floatValue());</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">float</span><span>&nbsp;newval&nbsp;=&nbsp;(&nbsp;mDiffMatrix.get(k).get(j).floatValue()&nbsp;+&nbsp;user.get(j).floatValue()&nbsp;)&nbsp;;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predictions.put(k,&nbsp;predictions.get(k)+newval);&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;predictions.keySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predictions.put(j,&nbsp;predictions.get(j).floatValue()/user.size());&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;user.keySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predictions.put(j,user.get(j));&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;predictions;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;printData()&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(UserId&nbsp;user&nbsp;:&nbsp;mData.keySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(user);&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(mData.get(user));&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i=</span><span class="number">0</span><span>;&nbsp;i&lt;mAllItems.length;&nbsp;i++)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(<span class="string">&quot;\n&quot;</span><span>&nbsp;+&nbsp;mAllItems[i]&nbsp;+&nbsp;</span><span class="string">&quot;:&quot;</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printMatrixes(mDiffMatrix.get(mAllItems[i]),&nbsp;mFreqMatrix.get(mAllItems[i]));&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;printMatrixes(Map&lt;ItemId,Float&gt;&nbsp;ratings,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;ItemId,Integer&gt;&nbsp;frequencies)&nbsp;{&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;j=</span><span class="number">0</span><span>;&nbsp;j&lt;mAllItems.length;&nbsp;j++)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.format(<span class="string">&quot;%10.3f&quot;</span><span>,&nbsp;ratings.get(mAllItems[j]));&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(<span class="string">&quot;&nbsp;&quot;</span><span>);&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.format(<span class="string">&quot;%10d&quot;</span><span>,&nbsp;frequencies.get(mAllItems[j]));&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println();&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;print(Map&lt;ItemId,Float&gt;&nbsp;user)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;user.keySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="string">&quot;&nbsp;&quot;</span><span>+&nbsp;j+&nbsp;</span><span class="string">&quot;&nbsp;--&gt;&nbsp;&quot;</span><span>+user.get(j).floatValue());&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;buildDiffMatrix()&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;mDiffMatrix&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Map&lt;ItemId,Float&gt;&gt;();&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;mFreqMatrix&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Map&lt;ItemId,Integer&gt;&gt;();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;first&nbsp;iterate&nbsp;through&nbsp;users</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(Map&lt;ItemId,Float&gt;&nbsp;user&nbsp;:&nbsp;mData.values())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;then&nbsp;iterate&nbsp;through&nbsp;user&nbsp;data</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(Map.Entry&lt;ItemId,Float&gt;&nbsp;entry:&nbsp;user.entrySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(!mDiffMatrix.containsKey(entry.getKey()))&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mDiffMatrix.put(entry.getKey(),&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Float&gt;());&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mFreqMatrix.put(entry.getKey(),&nbsp;<span class="keyword">new</span><span>&nbsp;HashMap&lt;ItemId,Integer&gt;());&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(Map.Entry&lt;ItemId,Float&gt;&nbsp;entry2:&nbsp;user.entrySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;oldcount&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(mFreqMatrix.get(entry.getKey()).containsKey(entry2.getKey()))&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oldcount&nbsp;=&nbsp;mFreqMatrix.get(entry.getKey()).get(entry2.getKey()).intValue();&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">float</span><span>&nbsp;olddiff&nbsp;=&nbsp;</span><span class="number">0</span><span>.0f;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(mDiffMatrix.get(entry.getKey()).containsKey(entry2.getKey()))&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;olddiff&nbsp;=&nbsp;mDiffMatrix.get(entry.getKey()).get(entry2.getKey()).floatValue();&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">float</span><span>&nbsp;observeddiff&nbsp;=&nbsp;entry.getValue()&nbsp;-&nbsp;entry2.getValue();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mFreqMatrix.get(entry.getKey()).put(entry2.getKey(),oldcount&nbsp;+&nbsp;<span class="number">1</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mDiffMatrix.get(entry.getKey()).put(entry2.getKey(),olddiff+observeddiff);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;j&nbsp;:&nbsp;mDiffMatrix.keySet())&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(ItemId&nbsp;i&nbsp;:&nbsp;mDiffMatrix.get(j).keySet())&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">float</span><span>&nbsp;oldvalue&nbsp;=&nbsp;mDiffMatrix.get(j).get(i).floatValue();&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;count&nbsp;=&nbsp;mFreqMatrix.get(j).get(i).intValue();&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mDiffMatrix.get(j).put(i,oldvalue/count);&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">class</span><span>&nbsp;UserId&nbsp;&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;String&nbsp;content;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;UserId(String&nbsp;s)&nbsp;{&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;content&nbsp;=&nbsp;s;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;hashCode()&nbsp;{&nbsp;</span><span class="keyword">return</span><span>&nbsp;content.hashCode();}&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;String&nbsp;toString()&nbsp;{&nbsp;</span><span class="keyword">return</span><span>&nbsp;content;&nbsp;}&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li><li><span><span class="keyword">class</span><span>&nbsp;ItemId&nbsp;&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;String&nbsp;content;&nbsp;</span></li><li><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;ItemId(String&nbsp;s)&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;content&nbsp;=&nbsp;s;&nbsp;</span></li><li><span>&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;hashCode()&nbsp;{&nbsp;</span><span class="keyword">return</span><span>&nbsp;content.hashCode();}&nbsp;</span></span></li><li><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;String&nbsp;toString()&nbsp;{&nbsp;</span><span class="keyword">return</span><span>&nbsp;content;&nbsp;}&nbsp;</span></span></li><li class="alt"><span>}&nbsp;</span></li></ol></pre>
<p>&nbsp;</p>
<p>Python：</p>
<pre><ol class="dp-py"><li class="alt"><span><span class="comment">#&nbsp;Copyright&nbsp;2006&nbsp;Bryan&nbsp;O'Sullivan&nbsp;&lt;bos@serpentine.com&gt;.</span><span>&nbsp;</span></span></li><li><span><span class="comment">#</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="comment">#&nbsp;This&nbsp;software&nbsp;may&nbsp;be&nbsp;used&nbsp;and&nbsp;distributed&nbsp;according&nbsp;to&nbsp;the&nbsp;terms</span><span>&nbsp;</span></span></li><li><span><span class="comment">#&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License,&nbsp;version&nbsp;2&nbsp;or&nbsp;later,&nbsp;which&nbsp;is</span><span>&nbsp;</span></span></li><li class="alt"><span><span class="comment">#&nbsp;incorporated&nbsp;herein&nbsp;by&nbsp;reference.</span><span>&nbsp;</span></span></li><li><span>&nbsp;</span></li><li class="alt"><span><span class="keyword">class</span><span>&nbsp;SlopeOne(object):&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">def</span><span>&nbsp;__init__(</span><span class="special">self</span><span>):&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.diffs&nbsp;=&nbsp;{}&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.freqs&nbsp;=&nbsp;{}&nbsp;</span></span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">def</span><span>&nbsp;predict(</span><span class="special">self</span><span>,&nbsp;userprefs):&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preds,&nbsp;freqs&nbsp;=&nbsp;{},&nbsp;{}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;item,&nbsp;rating&nbsp;</span><span class="keyword">in</span><span>&nbsp;userprefs.iteritems():&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;diffitem,&nbsp;diffratings&nbsp;</span><span class="keyword">in</span><span>&nbsp;</span><span class="special">self</span><span>.diffs.iteritems():&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span><span>:&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;freq&nbsp;=&nbsp;<span class="special">self</span><span>.freqs[diffitem][item]&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">except</span><span>&nbsp;KeyError:&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">continue</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preds.setdefault(diffitem,&nbsp;<span class="number">0.0</span><span>)&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;freqs.setdefault(diffitem,&nbsp;<span class="number">0</span><span>)&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preds[diffitem]&nbsp;+=&nbsp;freq&nbsp;*&nbsp;(diffratings[item]&nbsp;+&nbsp;rating)&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;freqs[diffitem]&nbsp;+=&nbsp;freq&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;dict([(item,&nbsp;value&nbsp;/&nbsp;freqs[item])&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;item,&nbsp;value&nbsp;</span><span class="keyword">in</span><span>&nbsp;preds.iteritems()&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;item&nbsp;</span><span class="keyword">not</span><span>&nbsp;</span><span class="keyword">in</span><span>&nbsp;userprefs&nbsp;</span><span class="keyword">and</span><span>&nbsp;freqs[item]&nbsp;&gt;&nbsp;</span><span class="number">0</span><span>])&nbsp;</span></span></li><li class="alt"><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">def</span><span>&nbsp;update(</span><span class="special">self</span><span>,&nbsp;userdata):&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;ratings&nbsp;</span><span class="keyword">in</span><span>&nbsp;userdata.itervalues():&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;item1,&nbsp;rating1&nbsp;</span><span class="keyword">in</span><span>&nbsp;ratings.iteritems():&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.freqs.setdefault(item1,&nbsp;{})&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.diffs.setdefault(item1,&nbsp;{})&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;item2,&nbsp;rating2&nbsp;</span><span class="keyword">in</span><span>&nbsp;ratings.iteritems():&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.freqs[item1].setdefault(item2,&nbsp;</span><span class="number">0</span><span>)&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.diffs[item1].setdefault(item2,&nbsp;</span><span class="number">0.0</span><span>)&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.freqs[item1][item2]&nbsp;+=&nbsp;</span><span class="number">1</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="special">self</span><span>.diffs[item1][item2]&nbsp;+=&nbsp;rating1&nbsp;-&nbsp;rating2&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;item1,&nbsp;ratings&nbsp;</span><span class="keyword">in</span><span>&nbsp;</span><span class="special">self</span><span>.diffs.iteritems():&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;item2&nbsp;</span><span class="keyword">in</span><span>&nbsp;ratings:&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ratings[item2]&nbsp;/=&nbsp;<span class="special">self</span><span>.freqs[item1][item2]&nbsp;</span></span></li><li class="alt"><span>&nbsp;</span></li><li><span><span class="keyword">if</span><span>&nbsp;__name__&nbsp;==&nbsp;</span><span class="string">'__main__'</span><span>:&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;userdata&nbsp;=&nbsp;dict(&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alice=dict(squid=<span class="number">1.0</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cuttlefish=<span class="number">0.5</span><span>,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;octopus=<span class="number">0.2</span><span>),&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bob=dict(squid=<span class="number">1.0</span><span>,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;octopus=<span class="number">0.5</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nautilus=<span class="number">0.2</span><span>),&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;carole=dict(squid=<span class="number">0.2</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;octopus=<span class="number">1.0</span><span>,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cuttlefish=<span class="number">0.4</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nautilus=<span class="number">0.4</span><span>),&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dave=dict(cuttlefish=<span class="number">0.9</span><span>,&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;octopus=<span class="number">0.4</span><span>,&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nautilus=<span class="number">0.5</span><span>),&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;=&nbsp;SlopeOne()&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;s.update(userdata)&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">print</span><span>&nbsp;s.predict(dict(squid=</span><span class="number">0.4</span><span>))&nbsp;</span></span></li></ol></pre>
<p>&nbsp;</p>
<p>&nbsp;=-========================== 延伸文章===========================</p>
<p><span style="color: rgb(192, 192, 192); ">来源 ：&nbsp;</span><a href="http://my.donews.com/clickstone/2006/10/16/fktEQWUckzvGDyfjugcqcJjkaDpdjemooGTf/"><span style="color: rgb(192, 192, 192); ">http://my.donews.com/clickstone/2006/10/16/fktEQWUckzvGDyfjugcqcJjkaDpdjemooGTf/</span></a></p>
<p>&nbsp;</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; "><em><font face="宋体" size="2">本文是关于推荐系统的系列研究文章之一，其他内容将陆续发布。这些内容，大多数来自我在2004年底完成的一篇项目方案建议书。放在这里，抛砖引玉，供大家讨论之用。<br />
－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</font></em></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">在推荐系统简介中，我们给出了推荐系统的一般框架。很明显，推荐方法是整个推荐系统中最核心、最关键的部分，很大程度上决定了推荐系统性能的优劣。目前，主要的推荐方法包括：基于内容推荐、协同过滤推荐、基于关联规则推荐、基于效用推荐、基于知识推荐和组合推荐。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; "><font face="黑体" size="3">一、基于内容推荐</font></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">基于内容的推荐（Content-based Recommendation）是信息过滤技术的延续与发展，它是建立在项目的内容信息上作出推荐的，而不需要依据用户对项目的评价意见，更多地需要用机 器学习的方法从关于内容的特征描述的事例中得到用户的兴趣资料。在基于内容的推荐系统中，项目或对象是通过相关的特征的属性来定义，系统基于用户评价对象 的特征，学习用户的兴趣，考察用户资料与待预测项目的相匹配程度。用户的资料模型取决于所用学习方法，常用的有决策树、神经网络和基于向量的表示方法等。 基于内容的用户资料是需要有用户的历史数据，用户资料模型可能随着用户的偏好改变而发生变化。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">基于内容推荐方法的优点是：<br />
 1）不需要其它用户的数据，没有冷开始问题和稀疏问题。<br />
 2）能为具有特殊兴趣爱好的用户进行推荐。<br />
 3）能推荐新的或不是很流行的项目，没有新项目问题。<br />
 4）通过列出推荐项目的内容特征，可以解释为什么推荐那些项目。<br />
 5）已有比较好的技术，如关于分类学习方面的技术已相当成熟。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">缺点是要求内容能容易抽取成有意义的特征，要求特征内容有良好的结构性，并且用户的口味必须能够用内容特征形式来表达，不能显式地得到其它用户的判断情况。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; "><font face="黑体" size="3">二、协同过滤推荐</font></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">协同过滤推荐（Collaborative Filtering Recommendation）技术是推荐系统中应用最早和最为成功的技术之一。它一般采用最近邻技术，利用用户的历史喜好信息计算用户之间的距离，然后 利用目标用户的最近邻居用户对商品评价的加权评价值来预测目标用户对特定商品的喜好程度，系统从而根据这一喜好程度来对目标用户进行推荐。协同过滤最大优 点是对推荐对象没有特殊的要求，能处理非结构化的复杂对象，如音乐、电影。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">协同过滤是基于这样的假设：为一用户找到他真正感兴趣的内容的好方法是首先找到与此用户有相似兴趣的其他用户，然后将他们感兴趣的内容推荐给此用 户。其基本思想非常易于理解，在日常生活中，我们往往会利用好朋友的推荐来进行一些选择。协同过滤正是把这一思想运用到电子商务推荐系统中来，基于其他用 户对某一内容的评价来向目标用户进行推荐。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">基于协同过滤的推荐系统可以说是从用户的角度来进行相应推荐的，而且是自动的，即用户获得的推荐是系统从购买模式或浏览行为等隐式获得的，不需要用户努力地找到适合自己兴趣的推荐信息，如填写一些调查表格等。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">和基于内容的过滤方法相比，协同过滤具有如下的优点：<br />
1） 能够过滤难以进行机器自动内容分析的信息，如艺术品，音乐等。<br />
2） 共享其他人的经验，避免了内容分析的不完全和不精确，并且能够基于一些复杂的，难以表述的概念（如信息质量、个人品味）进行过滤。<br />
3） 有推荐新信息的能力。可以发现内容上完全不相似的信息，用户对推荐信息的内容事先是预料不到的。这也是协同过滤和基于内容的过滤一个较大的差别，基于内容的过滤推荐很多都是用户本来就熟悉的内容，而协同过滤可以发现用户潜在的但自己尚未发现的兴趣偏好。<br />
4） 能够有效的使用其他相似用户的反馈信息，较少用户的反馈量，加快个性化学习的速度。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">虽然协同过滤作为一种典型的推荐技术有其相当的应用，但协同过滤仍有许多的问题需要解决。最典型的问题有稀疏问题（Sparsity）和可扩展问题（Scalability）。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; "><font face="黑体" size="3">三、基于关联规则推荐</font></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">基于关联规则的推荐（Association Rule-based Recommendation）是以关联规则为基础，把已购商品作为规则头，规则体为推荐对象。关联规则挖掘可以发现不同商品在销售过程中的相关性，在零 售业中已经得到了成功的应用。管理规则就是在一个交易数据库中统计购买了商品集X的交易中有多大比例的交易同时购买了商品集Y，其直观的意义就是用户在购 买某些商品的时候有多大倾向去购买另外一些商品。比如购买牛奶的同时很多人会同时购买面包。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">算法的第一步关联规则的发现最为关键且最耗时，是算法的瓶颈，但可以离线进行。其次，商品名称的同义性问题也是关联规则的一个难点。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; "><font face="黑体" size="3">四、基于效用推荐</font></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">基于效用的推荐（Utility-based Recommendation）是建立在对用户使用项目的效用情况上计算的，其核心问题是怎么样为每一个用户去创建一个效用函数，因此，用户资料模型很大 程度上是由系统所采用的效用函数决定的。基于效用推荐的好处是它能把非产品的属性，如提供商的可靠性（Vendor Reliability）和产品的可得性（Product Availability）等考虑到效用计算中。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; "><font face="黑体" size="3">五、基于知识推荐</font></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">基于知识的推荐（Knowledge-based Recommendation）在某种程度是可以看成是一种推理（Inference）技术，它不是建立在用户需要和偏好基础上推荐的。基于知识的方法因 它们所用的功能知识不同而有明显区别。效用知识（Functional Knowledge）是一种关于一个项目如何满足某一特定用户的知识，因此能解释需要和推荐的关系，所以用户资料可以是任何能支持推理的知识结构，它可以 是用户已经规范化的查询，也可以是一个更详细的用户需要的表示。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; "><font face="黑体" size="3">六、组合推荐</font></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">由于各种推荐方法都有优缺点，所以在实际中，组合推荐（Hybrid Recommendation）经常被采用。研究和应用最多的是内容推荐和协同过滤推荐的组合。最简单的做法就是分别用基于内容的方法和协同过滤推荐方法 去产生一个推荐预测结果，然后用某方法组合其结果。尽管从理论上有很多种推荐组合方法，但在某一具体问题中并不见得都有效，组合推荐一个最重要原则就是通 过组合后要能避免或弥补各自推荐技术的弱点。</p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">在组合方式上，有研究人员提出了七种组合思路：<br />
1）加权（Weight）：加权多种推荐技术结果。<br />
2）变换（Switch）：根据问题背景和实际情况或要求决定变换采用不同的推荐技术。<br />
3）混合（Mixed）：同时采用多种推荐技术给出多种推荐结果为用户提供参考。<br />
4）特征组合（Feature combination）：组合来自不同推荐数据源的特征被另一种推荐算法所采用。<br />
5）层叠（Cascade）：先用一种推荐技术产生一种粗糙的推荐结果，第二种推荐技术在此推荐结果的基础上进一步作出更精确的推荐。<br />
6）特征扩充（Feature augmentation）：一种技术产生附加的特征信息嵌入到另一种推荐技术的特征输入中。<br />
7）元级别（Meta-level）：用一种推荐方法产生的模型作为另一种推荐方法的输入。<br />
<font face="黑体" size="3">七、主要推荐方法的对比</font></p>
<p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">各种推荐方法都有其各自的优点和缺点，见表1。</p>
<table border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td colspan="3">
            <p align="center" style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">表1 主要推荐方法对比</p>
            </td>
        </tr>
        <tr>
            <td>推荐方法</td>
            <td>优点</td>
            <td>缺点</td>
        </tr>
        <tr>
            <td>基于内容推荐</td>
            <td>推荐结果直观，容易解释；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">不需要领域知识</p>
            </td>
            <td>新用户问题；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">复杂属性不好处理；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">要有足够数据构造分类器</p>
            </td>
        </tr>
        <tr>
            <td>协同过滤推荐</td>
            <td>新异兴趣发现、不需要领域知识；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">随着时间推移性能提高；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">推荐个性化、自动化程度高；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">能处理复杂的非结构化对象</p>
            </td>
            <td>稀疏问题；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">可扩展性问题；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">新用户问题；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">质量取决于历史数据集；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">系统开始时推荐质量差；</p>
            </td>
        </tr>
        <tr>
            <td>基于规则推荐</td>
            <td>能发现新兴趣点；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">不要领域知识</p>
            </td>
            <td>规则抽取难、耗时；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">产品名同义性问题；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">个性化程度低；</p>
            </td>
        </tr>
        <tr>
            <td>基于效用推荐</td>
            <td>无冷开始和稀疏问题；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">对用户偏好变化敏感；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">能考虑非产品特性</p>
            </td>
            <td>用户必须输入效用函数；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">推荐是静态的，灵活性差；</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">属性重叠问题；</p>
            </td>
        </tr>
        <tr>
            <td>基于知识推荐</td>
            <td>能把用户需求映射到产品上；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">能考虑非产品属性</p>
            </td>
            <td>知识难获得；
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">&nbsp;</p>
            <p style="margin-top: 0.5em; margin-right: 1em; margin-bottom: 0.8em; margin-left: 1em; line-height: 1.5em; ">推荐是静态的</p>
            <div>&nbsp;</div>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/staruml_to_as3.aspx]]></link>
	<title><![CDATA[利用 StarUML 创建 AS3 代码]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-2-27 15:43:33</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/staruml_to_as3.aspx]]></guid>
	<description><![CDATA[<p>最近在搜寻轻量好用且免费的UML工具，且最好能产生AS3代码的。&nbsp; 于是 StrarUML 进入我的视野。</p>
<p>在此处可以找到原文阐述如何使用此款软件: <a href="http://www.senocular.com/flash/tutorials/starumltoas3/">http://www.senocular.com/flash/tutorials/starumltoas3/</a></p>
<p>关键安装方式是：</p>
<ol>
    <li>下载 StrarUML <a href="http://www.staruml.com/">http://www.staruml.com/</a>&nbsp;。</li>
    <li>下载 AS3 代码生成模板&nbsp; <a href="http://www.senocular.com/flash/tutorials/starumltoas3/downloads/StarUML_ActionScript3_Export.zip">http://www.senocular.com/flash/tutorials/starumltoas3/downloads/StarUML_ActionScript3_Export.zip</a></li>
    <li>进入 StrarUML&nbsp;&nbsp; 所在的安装目录下 \modules\staruml-generator\templates 处将 模板中 ActionScript 3.0 整个文件夹放入到这里。<br />
    最后可以得到如下2个路径：&nbsp; <br />
    &lt;StarUML 安装目录&gt;\modules\staruml-generator\templates<font face="Courier New">\ActionScript 3.0\template description.tdf<br />
    <font face="Arial">&lt;StarUML 安装目录&gt;\modules\staruml-generator\templates</font><font face="Courier New">\ActionScript 3.0\template.cot</font></font></li>
</ol>
<p><font face="Courier New"><font face="Courier New"><font face="Arial">关键</font>使用方式：</font></font></p>
<ol>
    <li><font face="Courier New"><font face="Courier New">启动StarUML 并打开你要导出代码的 UML 视图。</font></font></li>
    <li><font face="Courier New"><font face="Courier New">选择&nbsp; Tools &gt; StarUML Generator</font></font></li>
    <li><font face="Courier New"><font face="Courier New">勾上 模板列表（list of template）中文档名(Document Name)为 ActionScript 3.0 选项。</font></font></li>
    <li><font face="Courier New"><font face="Courier New">点下 next</font></font></li>
    <li><font face="Courier New"><font face="Courier New">此时面板会让你选择导出路径。自己选择吧，比如直接可以倒入到 Src中。</font></font></li>
    <li><font face="Courier New"><font face="Courier New">选择完毕后点下 next</font></font></li>
    <li><font face="Courier New"><font face="Courier New">此时，会等待你决定是否立即产出代码</font></font></li>
    <li><font face="Courier New"><font face="Courier New">点Generate 即可。</font></font></li>
</ol>
<p>StarUML AS3例子：<br />
<a href="http://www.senocular.com/flash/tutorials/starumltoas3/downloads/Gallery.uml">http://www.senocular.com/flash/tutorials/starumltoas3/downloads/Gallery.uml</a></p>
<p>&nbsp;</p>
<p>另外再提供UML学习指南：<a href="http://www.uml.org.cn/oobject/OObject.asp">http://www.uml.org.cn/oobject/OObject.asp</a></p>
<p>&nbsp;</p>]]></description>
</item>
<item>
	<link><![CDATA[http://www.xintend.com/article/javascript_core_namespace.aspx]]></link>
	<title><![CDATA[JavaScript Core namespace]]></title>
	<author><![CDATA[KingFo]]></author>
	<category><![CDATA[开发者]]></category>
	<pubDate>2010-1-20 10:28:28</pubDate>
	<guid><![CDATA[http://www.xintend.com/article/javascript_core_namespace.aspx]]></guid>
	<description><![CDATA[<p>&nbsp;</p>
<script type="text/javascript" src="http://assets.taobaocdn.com/app/tms/tms-edit-link.js"></script>
<table width="90%" cellspacing="2">
    <tbody>
        <tr class="compheader">
            <th style="text-align: left;">Class</th>
            <th class="browser">IE<br />
            <img browser="IE" src="http://127.0.0.1:51045/help/nftopic/com.aptana.ide.documentation/content/button_off.gif" onclick="toggleRows(&quot;IE&quot;, this)" style="padding-top: 5px;" title="Hide items not available on this platform" alt="" /></th>
            <th class="browser">Mozilla<br />
            <img browser="Mozilla" src="http://127.0.0.1:51045/help/nftopic/com.aptana.ide.documentation/content/button_off.gif" onclick="toggleRows(&quot;Mozilla&quot;, this)" style="padding-top: 5px;" title="Hide items not available on this platform" alt="" /></th>
            <th class="browser">Netscape<br />
            <img browser="Netscape" src="http://127.0.0.1:51045/help/nftopic/com.aptana.ide.documentation/content/button_off.gif" onclick="toggleRows(&quot;Netscape&quot;, this)" style="padding-top: 5px;" title="Hide items not available on this platform" alt="" /></th>
            <th class="browser">Opera<br />
            <img browser="Opera" src="http://127.0.0.1:51045/help/nftopic/com.aptana.ide.documentation/content/button_off.gif" onclick="toggleRows(&quot;Opera&quot;, this)" style="padding-top: 5px;" title="Hide items not available on this platform" alt="" /></th>
            <th class="browser">Safari<br />
            <img browser="Safari" src="http://127.0.0.1:51045/help/nftopic/com.aptana.ide.documentation/content/button_off.gif" onclick="toggleRows(&quot;Safari&quot;, this)" style="padding-top: 5px;" title="Hide items not available on this platform" alt="" /></th>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Arguments.html">Arguments</a></div>
            <div class="description">An array of parameters passed to a function.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">4.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">3.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Array.html">Array</a></div>
            <div class="description">An array is an ordered list of elements.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">4.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">3.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Boolean.html">Boolean</a></div>
            <div class="description">The Boolean object is an object wrapper for a boolean  value.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">3.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">3.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Date.html">Date</a></div>
            <div class="description">Lets you work with dates and times.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">3.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">2.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Enumerator.html">Enumerator</a></div>
            <div class="description">Enumerator is a proprietary Microsoft object that  iterates over items in a group.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">4.0+</td>
            <td align="middle" title="Mozilla" class="comparison no">no</td>
            <td align="middle" title="Netscape" class="comparison no">no</td>
            <td align="middle" title="Opera" class="comparison no">no</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Error.html">Error</a></div>
            <div class="description">Represents a runtime error.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">5.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">6.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="EvalError.html">EvalError</a></div>
            <div class="description">The EvalError is thrown when the eval method is used  incorrectly.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">5.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">6.0+</td>
            <td align="middle" title="Opera" class="comparison no">no</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Function.html">Function</a></div>
            <div class="description">Every function in JavaScript is actually a Function  object.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">4.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">3.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Global.html">Global</a></div>
            <div class="description">The Global object is the parent of all globally avaliable  properties and methods.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">3.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">2.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Math.html">Math</a></div>
            <div class="description">A built-in object that has properties and methods for  mathematical constants and functions. For example, the Math object's PI property  has the value of pi.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">3.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">2.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Number.html">Number</a></div>
            <div class="description">Lets you work with numeric values. The Number object is  an object wrapper for primitive numeric values.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">3.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">3.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="Object.html">Object</a></div>
            <div class="description">Object is the primitive JavaScript object type. All  JavaScript objects are descended from Object. That is, all JavaScript objects  have the methods defined for Object.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">4.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">2.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="RangeError.html">RangeError</a></div>
            <div class="description">Thrown when a number is out of its appropriate  range.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">5.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">6.0+</td>
            <td align="middle" title="Opera" class="comparison no">no</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="ReferenceError.html">ReferenceError</a></div>
            <div class="description">Thrown if reading a variable that does not  exist.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">5.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">6.0+</td>
            <td align="middle" title="Opera" class="comparison no">no</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="RegExp.html">RegExp</a></div>
            <div class="description">Pattern for a regular expression.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">4.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">4.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="String.html">String</a></div>
            <div class="description">Represents the characters of a string.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">3.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">2.0+</td>
            <td align="middle" title="Opera" class="comparison yes">7.0+</td>
            <td align="middle" title="Safari" class="comparison yes">1.0+</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="SyntaxError.html">SyntaxError</a></div>
            <div class="description">A SyntaxError is thrown if there is a syntax error in the  JavaScript code.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">5.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">6.0+</td>
            <td align="middle" title="Opera" class="comparison no">no</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="TypeError.html">TypeError</a></div>
            <div class="description">A TypeError is thrown when a value is a different type  than what was expected.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">5.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">6.0+</td>
            <td align="middle" title="Opera" class="comparison no">no</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
        <tr>
            <td class="declaration">
            <div class="name"><a href="URIError.html">URIError</a></div>
            <div class="description">A URIError is thrown when there is an exception with URI  encoding or decoding.</div>
            </td>
            <td align="middle" title="IE" class="comparison yes">5.0+</td>
            <td align="middle" title="Mozilla" class="comparison yes">1.0+</td>
            <td align="middle" title="Netscape" class="comparison yes">6.0+</td>
            <td align="middle" title="Opera" class="comparison no">no</td>
            <td align="middle" title="Safari" class="comparison no">no</td>
        </tr>
    </tbody>
</table>]]></description>
</item>
</channel></rss>