<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>realazy</title>
	<atom:link href="http://realazy.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://realazy.org/blog</link>
	<description>web 标准，前端开发，编程感悟，生活杂想</description>
	<pubDate>Tue, 22 Jul 2008 08:26:53 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Web Forms 2.0</title>
		<link>http://realazy.org/blog/2008/07/22/web-forms-20/</link>
		<comments>http://realazy.org/blog/2008/07/22/web-forms-20/#comments</comments>
		<pubDate>Tue, 22 Jul 2008 08:26:53 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[Web 标准]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/?p=180</guid>
		<description><![CDATA[Web Forms 2.0 是一个很有意思的东东，是 HTML 5 的组成部分。它的目标是提升表单的使用性 (usability)，基本上就是为 input 元素的 type 属性增加一些值，如 type="email"；还有一些新属性，如 required。根据 type 由浏览器实现各种功能。比如，&#60;input type="email" required="required" /&#62;，从字面上即可看出，这是一个必须填写，且格式是电子邮件的输入框。如果你用的是 Opera 9+, 猛击这个例子看看效果。
注意，这不需要任何 JavaScript，是浏览器内部实现的功能。很遗憾的是到目前为止只有 Opera 9+ 有部分实现，作为前端开发者，每天都在为表单验证、自动完成等提升表单用户体验的事情上拼了老命，重复发明轮子。好消息是，基本上这些都可以通过 JavaScript 来模拟实现，项目当然有人在做了：webforms2，不妨下载一试。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.whatwg.org/specs/web-forms/current-work/">Web Forms 2.0</a> 是一个很有意思的东东，是 <a href="http://www.whatwg.org/specs/web-apps/current-work/">HTML 5</a> 的组成部分。它的目标是提升表单的使用性 (usability)，基本上就是为 <code>input</code> 元素的 <code>type</code> 属性增加一些值，如 <code>type="email"</code>；还有一些新属性，如 <code>required</code>。根据 <code>type</code> 由浏览器实现各种功能。比如，<code>&lt;input type="email" required="required" /&gt;</code>，从字面上即可看出，这是一个必须填写，且格式是电子邮件的输入框。如果你用的是 Opera 9+, 猛击<a href="http://shwetankdixit.com/testpages/webforms2demo.htm">这个例子</a>看看效果。</p>
<p>注意，这不需要任何 JavaScript，是浏览器内部实现的功能。很遗憾的是到目前为止只有 Opera 9+ 有部分实现，作为前端开发者，每天都在为表单验证、自动完成等提升表单用户体验的事情上拼了老命，重复发明轮子。好消息是，基本上这些都可以通过 JavaScript 来模拟实现，项目当然有人在做了：<a href="http://code.google.com/p/webforms2/">webforms2</a>，不妨下载一试。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/07/22/web-forms-20/feed/</wfw:commentRss>
		</item>
		<item>
		<title>使用标准的表单字段名</title>
		<link>http://realazy.org/blog/2008/06/28/using-rfc3106-stardard-field-nam/</link>
		<comments>http://realazy.org/blog/2008/06/28/using-rfc3106-stardard-field-nam/#comments</comments>
		<pubDate>Sat, 28 Jun 2008 04:45:11 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[Web 标准]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/?p=178</guid>
		<description><![CDATA[是不是很烦每次注册网站或填写相关资料时都要重来一遍？其实会有很多自动填写工具能代劳。比如使用 Mac, 在 Safari 的表单中，它可以足够聪明帮你从帐户资料中查找并填写一些相应的字段。Opera 也有相关功能，不过资料设置是在浏览器内。
当然，它们是根据表单的字段名称进行猜测与匹配的。如何给表单字段起个好名字，以方便自动填写工具的匹配，就变得有必要起来。
既然说“标准”，那名字肯定不是乱取的。RFC3106 据此而生。比方说，用户 ID 使用 Ecom_User_ID, 密码使用 Ecom_User_Password 等等，你可以访问该页面查看更多的对应实例。虽然商业气息比较浓重，但不妨碍我们的使用，以及给用户带来的便利。
]]></description>
			<content:encoded><![CDATA[<p>是不是很烦每次注册网站或填写相关资料时都要重来一遍？其实会有很多自动填写工具能代劳。比如使用 Mac, 在 Safari 的表单中，它可以足够聪明帮你从帐户资料中查找并填写一些相应的字段。Opera 也有相关功能，不过资料设置是在浏览器内。</p>
<p>当然，它们是根据表单的字段名称进行猜测与匹配的。如何给表单字段起个好名字，以方便自动填写工具的匹配，就变得有必要起来。</p>
<p>既然说“标准”，那名字肯定不是乱取的。<a href="http://www.ietf.org/rfc/rfc3106">RFC3106</a> 据此而生。比方说，用户 ID 使用 Ecom_User_ID, 密码使用 Ecom_User_Password 等等，你可以访问该页面查看更多的对应实例。虽然商业气息比较浓重，但不妨碍我们的使用，以及给用户带来的便利。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/06/28/using-rfc3106-stardard-field-nam/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Refactoring HTML 书评</title>
		<link>http://realazy.org/blog/2008/05/27/refactoring-html-review/</link>
		<comments>http://realazy.org/blog/2008/05/27/refactoring-html-review/#comments</comments>
		<pubDate>Mon, 26 May 2008 16:02:21 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[Web 标准]]></category>

		<category><![CDATA[书评]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/?p=177</guid>
		<description><![CDATA[很多年以前，面对上古时代遗留的 HTML 发出的腐臭，我捂住鼻子唉声叹气。刚练熟 web 标准的我，恨不得寝其尸食其肉，把一切推翻重来。但经理说，没有时间浪费在清理这些垃圾上，快给我把新的页面切了！可想而知，我是郁闷的。你也是，别装了，我知道。我常常处于崩溃边缘，作为一个有深度爱心和追求完美（这应该是所有程序员追求的品质）的 web 前端开发者来说，为何不许我为残障者着想，改善一些无障碍性？为何不许我把这些鸟b（读者最好不要连起来念），鸟i, 还有鸟u送上刑场？看着 W3C 校验器显示出的一串又一串的 erorr, 我灰心丧气，横眉冷对经理指，好像丫欠了我几十万块冥币，哦不，人民币……
皆因我不知道“重构”(refactoring)。
或许你第一次看到这个词，会欢呼雀跃，耶，“重构”，网站重构，一切重新再来？很明显，不是。相反，它的过程是逐步的，有时甚至是很微小的。作为一门在编程中的高级技术，重构是指“在不改变代码外在行为的前提下，对代码作出修改，以改进程序的内部结构”（《重构：改善既有代码的设计》，2003，中国电力出版社）。对于 HTML 来说，就是不改变 HTML 所表达意义的基础上，对 HTML 作出修改，以改进 HTML 的内部结构。是不是很简单？
读者都知道 web 标准的意义所在，很明显，重构的目的是改善既有的 HTML，向 web 标准进军。重点在于改善，而不是取代。在很多情况下，取代的代价远比改善大得多。如果才能做到最大化的投入产出比，很明显，答案是重构。
啰嗦这么多，到底怎么重构？特别是 HTML, 怎么重构啊，看着堆垃圾我就头痛，是不？很多公司的网站，我们可以看到，比如腾讯，雅虎的新推出的页面，都是基于 web 标准的了，但还是存在大量的旧页面，就算访问量巨大，也是纹丝不动。我相信，这很大程度上不是由于不想改，而是除了全盘推翻重头再来之外，实在找不到好的解决办法。重构是你的解药，宝贝。
由世界知名的 XML 专家 Elliotte Rusty Harold 所著的 Refactoring HTML: Improving the Design of Existing Web Applications 是你解药的配方。书中大谈特谈的章节不多，就第一章说说who, what, why, when, where，其他章节都是说 how. how, yeah, 就是到底怎么重构的锦囊妙计。书中从编程世界中“窃取”被证明是可行的、成熟的技术，很多可能是 web 标准实践者闻所未闻的技术，结合到 [...]]]></description>
			<content:encoded><![CDATA[<p>很多年以前，面对上古时代遗留的 HTML 发出的腐臭，我捂住鼻子唉声叹气。刚练熟 web 标准的我，恨不得寝其尸食其肉，把一切推翻重来。但经理说，没有时间浪费在清理这些垃圾上，快给我把新的页面切了！可想而知，我是郁闷的。你也是，别装了，我知道。我常常处于崩溃边缘，作为一个有深度爱心和追求完美（这应该是所有程序员追求的品质）的 web 前端开发者来说，为何不许我为残障者着想，改善一些无障碍性？为何不许我把这些鸟<code>b</code>（读者最好不要连起来念），鸟<code>i</code>, 还有鸟<code>u</code>送上刑场？看着 W3C 校验器显示出的一串又一串的 erorr, 我灰心丧气，横眉冷对经理指，好像丫欠了我几十万块冥币，哦不，人民币……</p>
<p>皆因我不知道“<strong>重构</strong>”(refactoring)。</p>
<p>或许你第一次看到这个词，会欢呼雀跃，耶，“重构”，网站重构，一切重新再来？很明显，不是。相反，它的过程是逐步的，有时甚至是很微小的。作为一门在编程中的高级技术，重构是指“在不改变代码外在行为的前提下，对代码作出修改，以改进程序的内部结构”（《重构：改善既有代码的设计》，2003，中国电力出版社）。对于 HTML 来说，就是不改变 HTML 所表达意义的基础上，对 HTML 作出修改，以改进 HTML 的内部结构。是不是很简单？</p>
<p>读者都知道 web 标准的意义所在，很明显，重构的目的是改善既有的 HTML，向 web 标准进军。重点在于<strong>改善</strong>，而不是取代。在很多情况下，取代的代价远比改善大得多。如果才能做到最大化的投入产出比，很明显，答案是重构。</p>
<p>啰嗦这么多，到底怎么重构？特别是 HTML, 怎么重构啊，看着堆垃圾我就头痛，是不？很多公司的网站，我们可以看到，比如腾讯，雅虎的新推出的页面，都是基于 web 标准的了，但还是存在大量的旧页面，就算访问量巨大，也是纹丝不动。我相信，这很大程度上不是由于不想改，而是除了全盘推翻重头再来之外，实在找不到好的解决办法。重构是你的解药，宝贝。</p>
<p>由世界知名的 XML 专家 Elliotte Rusty Harold 所著的 <a href="http://www.amazon.com/Refactoring-HTML-Improving-Applications-Addison-Wesley/dp/0321503635/ref=pd_bbs_sr_1?ie=UTF8&#038;s=books&#038;qid=1211817642&#038;sr=8-1"><cite>Refactoring HTML: Improving the Design of Existing Web Applications</cite></a> 是你解药的配方。书中大谈特谈的章节不多，就第一章说说who, what, why, when, where，其他章节都是说 how. how, yeah, 就是到底怎么重构的锦囊妙计。书中从编程世界中“窃取”被证明是可行的、成熟的技术，很多可能是 web 标准实践者闻所未闻的技术，结合到 HTML 来，创造行之有效的新技术，解决 HTML 特有的难题。比方说，你关心过 GET 和 POST 是什么吗？知道为何 Google 爬虫爬一爬，很多页面消失殆尽吗？（嗯嗯，老油条们，我知道你知道（绕吧？），我在这里问的是“页面仔”）。关心过自动化测试吗？什么，你还刀耕火种，写一行就在浏览器刷一下看效果？知道怎么样批量校验你的页面吗？不要告诉我你一页又一页的把上千个页面轮番轰炸 W3C Validator&#8230;</p>
<p>不知道？那怎么还浪费时间看什么书评，赶紧的打开书来看啊！噢哦，没有书？google 一下，有得下。英文看不懂？很吃力？噢哦，明年中文版就会上市，嗯嗯，译者就是我……（终于露出狰狞面目）……</p>
<p>本书是探讨 HTML 领域的重构，是对重构这门技术的又一创造性运行。它从工具入手（我们知道，工具是重构的重要辅助），然后逐一分析良构（well-formness）、合法性、布局、无障碍、web 应用程序和内容等等需要重构的方面，提出问题，讨论理据（motivation）并提供行之有效的解决方案（mechanics）。对于接触 web 标准较少的人来说，提供了一个百科全书式的的参考，而对于我的同行们，sure, 亲爱的页面仔们，不仅可以查漏补缺，亦可学习程序工业中的先进经验，提升自己的“工业”素养。总之，这不是一本束之高阁的书。</p>
<p>编写 HTML 不仅是一门技术，更是一门艺术。你会了解的，在读了本书之后。在此我很严肃地说。仅以此献给中国所有的页面仔，共勉。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/05/27/refactoring-html-review/feed/</wfw:commentRss>
		</item>
		<item>
		<title>富文本编辑器的基本原理与实践</title>
		<link>http://realazy.org/blog/2008/05/02/rte-basis/</link>
		<comments>http://realazy.org/blog/2008/05/02/rte-basis/#comments</comments>
		<pubDate>Thu, 01 May 2008 21:18:16 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/05/02/rte-basis/</guid>
		<description><![CDATA[富文本编辑器，Rich Text Editor, 简称 RTE, 它提供类似于 Microsoft Word 的编辑功能，容易被不会编写 HTML 的用户并需要设置各种文本格式的用户所喜爱。它的应用也越来越广泛。最先只有 IE 浏览器支持，其它浏览器相继跟进，在功能的丰富性来说，还是 IE 强些。虽然没有一个统一的标准，但对于最基本的功能，各浏览器提供的 API 基本一致，从而使编写一个跨浏览器的富文本编辑器成为可能。
在很多开发者看来，富文本编辑器的编写是一件很神秘或者复杂的事情。神秘倒没有，复杂的话，确实如此。但是它的基本原理并不复杂，入门也不难。今天我们的主题是讲述基本原理，并逐步演示一个简单富文本编辑器的产生。这是我在 D2 上的一个分享内容，在台上的演讲效果不佳，固写下来，希望能够对感兴趣的读者有所帮助。
富文本编辑器的基本原理
这个原理实在是太简单了！对于支持富文本编辑的浏览器来说，其实就是设置 document 的 designMode 属性为 on 后，再通过执行 document.execCommand('commandName'[, UIFlag[, value]]) 即可。commandName 和 value 可以在 MSDN 上和MDC 上找到，它们就是我们创建各种格式的命令，比方说，我们要加粗字体，执行 document.execCommand('bold', false) 即可。很简单是吧？但是值得注意的是，通常是选中了文本后才执行命令，被选中的文本才被格式化。对于未选中的文本进行这个命令，各浏览器有不同的处理方式，比方 IE 可能是对位于光标中的标签内容进行格式化，而其它浏览器不做任何处理，这超出本文的内容，不细述。同时需要注意的是，UIFlag 这个参数设置为 true 表示 display any user interface triggered by the command (if any), 在我们今天的教程中都是 false, [...]]]></description>
			<content:encoded><![CDATA[<p>富文本编辑器，Rich Text Editor, 简称 RTE, 它提供类似于 Microsoft Word 的编辑功能，容易被不会编写 HTML 的用户并需要设置各种文本格式的用户所喜爱。它的应用也越来越广泛。最先只有 IE 浏览器支持，其它浏览器相继跟进，在功能的丰富性来说，还是 IE 强些。虽然没有一个统一的标准，但对于最基本的功能，各浏览器提供的 API 基本一致，从而使编写一个跨浏览器的富文本编辑器成为可能。</p>
<p>在很多开发者看来，富文本编辑器的编写是一件很神秘或者复杂的事情。神秘倒没有，复杂的话，确实如此。但是它的基本原理并不复杂，入门也不难。今天我们的主题是讲述基本原理，并逐步演示一个简单富文本编辑器的产生。这是我在 <a href="http://www.d2forum.cn/">D2</a> 上的一个分享内容，在台上的演讲效果不佳，固写下来，希望能够对感兴趣的读者有所帮助。</p>
<h2>富文本编辑器的基本原理</h2>
<p>这个原理实在是太简单了！对于支持富文本编辑的浏览器来说，其实就是设置 <code>document</code> 的 <code>designMode</code> 属性为 <code>on</code> 后，再通过执行 <code>document.execCommand('commandName'[, UIFlag[, value]]) </code>即可。<code>commandName</code> 和 <code>value</code> 可以在 <a href="http://msdn.microsoft.com/en-us/library/ms533049(VS.85).aspx">MSDN 上</a>和<a href="http://developer.mozilla.org/en/docs/Rich-Text_Editing_in_Mozilla">MDC 上</a>找到，它们就是我们创建各种格式的命令，比方说，我们要加粗字体，执行 <code>document.execCommand('bold', false)</code> 即可。很简单是吧？但是值得注意的是，通常是选中了文本后才执行命令，被选中的文本才被格式化。对于未选中的文本进行这个命令，各浏览器有不同的处理方式，比方 IE 可能是对位于光标中的标签内容进行格式化，而其它浏览器不做任何处理，这超出本文的内容，不细述。同时需要注意的是，<code>UIFlag</code> 这个参数设置为 <code>true</code> 表示 display any user interface triggered by the command (if any), 在我们今天的教程中都是 <code>false</code>, 而 <code>value</code> 也只在某些 <code>commandName</code> 中才有，具体参考以上刚给出的两个链接。</p>
<p>为了不影响当前 <code>document</code>, 通常的做法是在页面中嵌入一个 <code>iframe</code> 元素，然后对这个 <code>iframe</code> 内的 <code>document</code>（通过 <code>iframe.contentWindow.document</code> 获得）进行操作。</p>
<p>十分简单，是吧？下面我们来动手做一个。</p>
<h2>编写一个简单的富文本编辑器</h2>
<p>这个例子使用了 <a href="http://developer.yahoo.com/yui/">YUI</a>. 即使你对它不是很熟悉也没有关系，我在这里只使用了它的 DOM 和 Event 的一些跨平台基本方法。</p>
<h3>搭架</h3>
<p>在此强调一下很久未曾提及的 unobtrusive. 我们的编辑器是对 <code>textarea</code> 元素的一个增强（enhencement），就是说，即使 JavaScript 被禁用了，用户还可以通过 <code>textarea</code> 编辑内容。</p>
<p>在这个例子中，我们将使用 <code>YAHOO.realazy</code> 的命名空间，在之下实现一个 <code>RTE</code> 的类。我们今天的编辑器很简单，因此构造器(constructor) 的参数也只有 <code>textarea</code> 一个。我们使用一个实例变量来保存工具条的各个项目。实例初始化放到一个叫 <code>render</code> 的方法中。这一步的页面和代码见<a href="http://realazy.org/lab/rte/1.html">第 1 步</a>。</p>
<h3>创建 <code>iframe</code> 并替换 <code>textarea</code></h3>
<p>搭好架子，正如我在前面所说，建立一个 <code>iframe</code>, 编辑器的所有操作都在 <code>iframe</code> 的 <code>document</code> 内执行。并且把 textarea 隐藏起来。从<a href="http://realazy.org/lab/rte/2.html">第 2 步</a>中可以看到，我们已经有了一个 <code>iframe</code>, 但不能输入任何东西，很正常，我们没有打开它的 <code>designMode</code> 嘛。</p>
<h3>开启 <code>designMode</code></h3>
<p>这一步涉及的东西挺多，也是关键。我们会创建获取 <code>iframe</code> 的 <code>document</code> 的方法，并通过程序的方式向 <code>iframe</code> 写入空页而非使用一个外接的 blank.html. 我们使用一个类属性 <code> YAHOO.realazy.RTE.htmlContent</code> 来保存空页的 <code>html</code>. 在准备好一切后，就可以开启 <code>designMode</code> 了。页面和代码详见<a href="http://realazy.org/lab/rte/3.html">第 3 步</a>。看，我们已经可以在 <code>iframe</code> 里输入东西了。</p>
<h3>构建工具条</h3>
<p>我们需要操作的工具条！这样才可以控制 <code>iframe</code> 里的内容，才能称之为编辑器。在此我并不打算实现太多的功能，只是选择字形、字号、加粗、斜体、下划线、居左、居中、居右、超链接和插图作为示例。对于跨平台，<a href="http://www.mozilla.org/editor/midas-spec.html">Mozilla Midas Specification </a>是不错的参考。ok, 请看<a href="http://realazy.org/lab/rte/4.html">第 4 步</a>，我们的工具条出来了，虽然很丑。我同时用 CSS 对 <code>iframe</code> 的宽度做出了一些调整。</p>
<h3>给工具条加上事件</h3>
<p>嗯，工具条出来了，编辑器看起来也“人模狗样”了，你兴奋的点啊点，没什么效果……意料中嘛。我们接着给工具条绑定一些事件，让编辑器内容能够响应工具条。在这一步，我们把 <code>execCommand</code> 再封一层，前面说过，我们用不上 <code>UIFlag</code>，让它永远是 <code>false</code> 好了。好，有代码就有真相，请看<a href="http://realazy.org/lab/rte/5.html">第 5 步</a>。如果是正使用 IE, 请先暂时转移到其它浏览器。看到了吧，工具条生效了！</p>
<h3>解决 IE 的问题</h3>
<p>well, 如果你没有听我的劝告，依然使用 IE, 你会发现除了字型和字号其它的都不能用。为什么呢？你观察一下，有没有发现，其它浏览器选择文本后，再点击工具条上的项目，被选中的文本是否依然选中的？而 IE 呢，在点击工具条时，选中的文本马上失去选中的状态，所以它们就失败了。所以，如果我们能够保证点击工具条文本保持选中状态，就可以解决 IE 的问题了。</p>
<p>Microsoft 给 HTML 标签一个很奇怪的属性 <code>unselectable</code>, 只要设置为 <code>on</code>, 焦点不会转移到点击的元素上，从而保证文本的选中状态。</p>
<p>请看<a href="http://realazy.org/lab/rte/6.html">第 6 步</a>。这也是解决 IE 头痛问题的关键所在。我曾经在这上面费了很大脑筋。</p>
<h2>高级主题展望</h2>
<p>good, 看看我们现在的代码，224 行。相比其它动辄上万行的编辑器，你可能会觉得不可思议。因为我们这个最基本的编辑器，连 <code>selection</code> 都没有用到。很多很酷的效果，比如 Google Doc 里能够动态改变链接文本，使用页内层而非弹出的 <code>prompt</code> 来操作等高级功能，基本上都要用到 <code>TextRange</code>(IE) 或者 <code>Range</code>(W3C). 要命的是这两个东西互补兼容，只是相似而已。入门推荐看PPK 的 <a href="http://www.quirksmode.org/dom/range_intro.html">Introduction to Range</a>.</p>
<p>在此我们就不深入了，等我有时间我会总结一些奇技淫巧（呜呼，前端开发需要的奇技淫巧太多了，这不是好事情）出来。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/05/02/rte-basis/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JavaScript Memoization</title>
		<link>http://realazy.org/blog/2008/04/22/javascript-memoization/</link>
		<comments>http://realazy.org/blog/2008/04/22/javascript-memoization/#comments</comments>
		<pubDate>Tue, 22 Apr 2008 15:57:44 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/04/22/javascript-memoization/</guid>
		<description><![CDATA[Memoization 是一种将函数返回值缓存起来的方法，在 Lisp, Ruby, Perl, Python 等语言中使用非常广泛。随着 Ajax 的兴起，客户端对服务器的请求越来越密集（经典如 autocomplete），如果有一个良好的缓存机制，那么客户端 JavaScript 程序的效率的提升是显而易见的。
Memoization 原理非常简单，就是把函数的每次执行结果都放入一个散列表中，在接下来的执行中，在散列表中查找是否已经有相应执行过的值，如果有，直接返回该值，没有才真正执行函数体的求值部分。很明显，找值，尤其是在散列中找值，比执行函数快多了。现代 JavaScript 的开发也已经大量使用这种技术。
我通过 Google 寻找了好几种 JavaScript Memoization 的实现，都不太如人愿，有的实现不能缓存递归函数，有的需要修改函数的 prototype，于是自己实现一个：
/**
 * JavaScript Momoization
 * @param {string} func name of function / method
 * @param {object} [obj] mothed&#8217;s object or scope correction object
 *
 * MIT / BSD license
 */

function Memoize(func, obj){
    [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Memoization">Memoization</a> 是一种将函数返回值缓存起来的方法，在 Lisp, Ruby, Perl, Python 等语言中使用非常广泛。随着 Ajax 的兴起，客户端对服务器的请求越来越密集（经典如 autocomplete），如果有一个良好的缓存机制，那么客户端 JavaScript 程序的效率的提升是显而易见的。</p>
<p>Memoization 原理非常简单，就是把函数的每次执行结果都放入一个散列表中，在接下来的执行中，在散列表中查找是否已经有相应执行过的值，如果有，直接返回该值，没有才真正执行函数体的求值部分。很明显，找值，尤其是在散列中找值，比执行函数快多了。现代 JavaScript 的开发也已经大量使用这种技术。</p>
<p>我通过 Google <a href="http://www.google.com/search?hl=en&amp;hs=y9z&amp;q=JavaScript+Memoization">寻找</a>了好几种 JavaScript Memoization 的实现，都不太如人愿，有的实现不能缓存递归函数，有的需要修改函数的 <code>prototype</code>，于是自己实现一个：</p>
<pre><code>/**
 * JavaScript Momoization
 * @param {string} func name of function / method
 * @param {object} [obj] mothed&#8217;s object or scope correction object
 *
 * MIT / BSD license
 */

function Memoize(func, obj){
    var obj = obj || window,
        func = obj[func],
        cache = {};
    return function(){
        <del>var key = Array.prototype.join.call(arguments, &quot;&quot;);</del>
        var key = Array.prototype.join.call(arguments, &quot;_&quot;)
        if (!(key in cache))
            cache[key] = func.apply(obj, arguments);
        return cache[key];
    }
}</code></pre>
<p>并写了一个测试案例，空口无凭，让大家亲自看看 Memoization 的威力。</p>
<p>见：<a href="http://realazy.org/lab/memoization.html">http://realazy.org/lab/memoization.html</a></p>
<p>另，例子中的 fibonacci 函数有很多更有效率的实现方法，在此我使用最无效率的递归实现，只是为了更直达地演示 memoization.</p>
<p>又，longwosion 留言所提到的 key 唯一性问题，我略作修正，但应该还有更好的办法，欢迎您留言探讨。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/04/22/javascript-memoization/feed/</wfw:commentRss>
		</item>
		<item>
		<title>测试 Google App Engine</title>
		<link>http://realazy.org/blog/2008/04/11/google-app-engine-chatroom-demo/</link>
		<comments>http://realazy.org/blog/2008/04/11/google-app-engine-chatroom-demo/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 14:57:09 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/04/11/google-app-engine-chatroom-demo/</guid>
		<description><![CDATA[一不小心从某 blog 中第一时间发现 Google App Engine 发布，立马注册一个。当天晚上抽空看了看文档，做了做hello world，第二天晚上开始写一个聊天室程序，第三天晚上拿出 Python 技术手册，捣腾到今天才把一个简单的东西弄出来。去年学了一段时间的 Python, 还用 webpy 写了一个不成型的 blog 系统。某段时间认识自己不足，苦读了两个月的 C，后来买了 macbook, 又一头扎进 Objective-C 和 Cocoa, 哈哈哈，总之，一事无成吧。现在 GAE 出来了，突然发现一直寻找的 Python hosting 就这么从天上掉下来了，而且还是馅饼……重新激起 Python 兴趣，却发现又忘得差不多了……
废话太多了……这个测试 demo 叫 chatlazy, 位于 http://chatlazy.appspot.com. 是一个简易聊天室，后台部分，就是 Python 了，具体一点，是 webpy 0.3 (开发版，未发布)。机制十分简单，就是前端使用  JavaScript 隔 5 秒去提取后台的最新消息。有几个小细节还是值得总结一下的：

由于 GAE 的数据 ID 使不能用在 Gql 中的，我只能通过时间戳来比对消息状态。把 datetime 和秒数 ＋ [...]]]></description>
			<content:encoded><![CDATA[<p>一不小心从某 blog 中第一时间发现 Google App Engine 发布，立马注册一个。当天晚上抽空看了看文档，做了做hello world，第二天晚上开始写一个聊天室程序，第三天晚上拿出 <a href="http://www.oreilly.com.cn/book.php?bn=7-5641-0576-3">Python 技术手册</a>，捣腾到今天才把一个简单的东西弄出来。去年学了一段时间的 Python, 还用 <a href="http://webpy.org">webpy</a> 写了一个不成型的 blog 系统。某段时间认识自己不足，苦读了两个月的 C，后来买了 macbook, 又一头扎进 Objective-C 和 Cocoa, 哈哈哈，总之，一事无成吧。现在 GAE 出来了，突然发现一直寻找的 Python hosting 就这么从天上掉下来了，而且还是馅饼……重新激起 Python 兴趣，却发现又忘得差不多了……</p>
<p>废话太多了……这个测试 demo 叫 chatlazy, 位于 <a href="http://chatlazy.appspot.com">http://chatlazy.appspot.com</a>. 是一个简易聊天室，后台部分，就是 Python 了，具体一点，是 webpy 0.3 (开发版，未发布)。机制十分简单，就是前端使用  JavaScript 隔 5 秒去提取后台的最新消息。有几个小细节还是值得总结一下的：</p>
<ol>
<li>由于 GAE 的数据 ID 使不能用在 Gql 中的，我只能通过时间戳来比对消息状态。把 <code>datetime</code> 和秒数 ＋ 毫秒数的互转，还是比较繁琐的。Python 技术手册帮了我很大忙。解决方案大致如此：
<pre><code>str(time.mktime(d.timetuple()))[:-1] + str(d.microsecond)</code></pre>
<p>反过来则是：</p>
<pre><code>p = str(t).split('.')
tp = time.localtime(float(p[0]))
dt = datetime(tp[0], tp[1], tp[2], tp[3], tp[4], tp[5]+1, int(p[1]))</code></pre>
</li>
<li>对于 <code>iterable</code> 的对象, 先要 <code>list</code> 它转成列表，才可以使用 <code>reversed</code> 等相关方法。</li>
<li>需要取最新的 n 条信息，即数据库末尾的 n 条，但是又要顺序，可以先按逆序取 n 条，再反向排序（由此引发上条启示）。</li>
<li>对于任何用户输入的东西都要做过滤，一开始我在用户名那块忽略了，结果马上有人 XSS 了。这应该是基本常识，应铭记于心。</li>
<li>一定要处理异常。</li>
</ol>
<p>由于 GAE 这个天上掉的馅饼，我想我近期的精力会放到 Python 上了，有计划地把 blog 迁徙到 GAE 上，并开发一些有趣地程序。GAE rocks.  老实说，这是搜索、Gmail 后，对我而言可以排到第三的 Google 服务了。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/04/11/google-app-engine-chatroom-demo/feed/</wfw:commentRss>
		</item>
		<item>
		<title>认识延迟时间为 0 的 setTimeout</title>
		<link>http://realazy.org/blog/2008/03/29/understand-0-settimeout/</link>
		<comments>http://realazy.org/blog/2008/03/29/understand-0-settimeout/#comments</comments>
		<pubDate>Sat, 29 Mar 2008 13:24:00 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/03/29/understand-0-settimeout/</guid>
		<description><![CDATA[由 John Resig 的 How JavaScript Timers Work 可以知道，现有的 JavaScript 引擎是单线程处理任务的。它把任务放到队列中，不会同步去执行，必须在完成一个任务后才开始另外一个任务。
让我们看看我之前的文章：JavaScript的9个陷阱及评点，在第 9 点 Focus Pocus 中提到的问题。原作者对这个认识有所偏差，其实不只是 IE 的问题，而是现有 JavaScript 引擎对于线程实现的问题（关于线程，我的概念其实不多，如果不对，希望读者多多指教）。我们通过一个例子来说明，请访问 http://realazy.org/lab/settimeout.html. 我们来看 1 和 2。如果你能看看源代码，会发现我们的任务很简单，就是给文档增加一个 input 文本框，并聚焦和选中。请现在分别点击一下，可以看到，1 并没有能够聚焦和选中，而 2 可以。它们之间的区别在于，在执行
input.focus();
input.select();
时， 2 多了一个延迟时间为 0 的 setTimeout 的外围函数，即：
setTimeout(function(){
	input.focus();
	input.select();
}, 0);
按照 JavaScript: The Definitive Guide 5th 的 14.1 所说：

在实践中，setTimeout 会在其完成当前任何延宕事件的事件处理器的执行，以及完成文档当前状态更新后，告诉浏览器去启用 setTimeout 内注册的函数。

其实，这是一个把需要执行的任务从队列中跳脱的技巧。回到前面的例子，JavaScript 引擎在执行 onkeypress 时，由于没有多线程的同步执行，不可能同时去处理刚创建元素的 focus 和 select 事件，由于这两个事件都不在队列中，在完成 [...]]]></description>
			<content:encoded><![CDATA[<p>由 John Resig 的 <a href="http://ejohn.org/blog/how-javascript-timers-work/">How JavaScript Timers Work</a> 可以知道，现有的 JavaScript 引擎是单线程处理任务的。它把任务放到队列中，不会同步去执行，必须在完成一个任务后才开始另外一个任务。</p>
<p>让我们看看我之前的文章：<a href="http://realazy.org/blog/2007/08/20/nine-javascript-gotchas/">JavaScript的9个陷阱及评点</a>，在第 9 点 Focus Pocus 中提到的问题。原作者对这个认识有所偏差，其实不只是 IE 的问题，而是现有 JavaScript 引擎对于线程实现的问题（关于线程，我的概念其实不多，如果不对，希望读者多多指教）。我们通过一个例子来说明，请访问 <a href="http://realazy.org/lab/settimeout.html">http://realazy.org/lab/settimeout.html</a>. 我们来看 1 和 2。如果你能看看源代码，会发现我们的任务很简单，就是给文档增加一个 <code>input</code> 文本框，并聚焦和选中。请现在分别点击一下，可以看到，1 并没有能够聚焦和选中，而 2 可以。它们之间的区别在于，在执行</p>
<pre><code>input.focus();
input.select();</code></pre>
<p>时， 2 多了一个延迟时间为 0 的 <code>setTimeout</code> 的外围函数，即：</p>
<pre><code>setTimeout(function(){
	input.focus();
	input.select();
}, 0);</code></pre>
<p>按照 JavaScript: The Definitive Guide 5th 的 14.1 所说：</p>
<blockquote>
<p>在实践中，<code>setTimeout</code> 会在其完成当前任何延宕事件的事件处理器的执行，以及完成文档当前状态更新后，告诉浏览器去启用 <code>setTimeout</code> 内注册的函数。</p>
</blockquote>
<p>其实，这是一个把需要执行的任务从队列中跳脱的技巧。回到前面的例子，JavaScript 引擎在执行 <code>onkeypress</code> 时，由于没有多线程的同步执行，不可能同时去处理刚创建元素的 <code>focus</code> 和 <code>select</code> 事件，由于这两个事件都不在队列中，在完成 <code>onkeypress</code> 后，JavaScript 引擎已经丢弃了这两个事件，正如你看到的例子 1 的情况。而在例子 2 中，由于<code>setTimeout</code>可以把任务从某个队列中跳脱成为新队列，因而能够得到期望的结果。</p>
<p>这才是延迟事件为 0 的<code>setTimeout</code>的真正目的。在此，你可以看看例子 3，它的任务是实时更新输入的文本，现在请试试，你会发现预览区域总是落后一拍，比如你输 a, 预览区并没有出现 a, 在紧接输入 b 时， a 才不慌不忙地出现。其实我们是有办法让预览区跟输入框同步地，在此我没有给出答案，因为上面所说的，就是解决思路，try it yourself!</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/03/29/understand-0-settimeout/feed/</wfw:commentRss>
		</item>
		<item>
		<title>《精通 JavaScript》上市</title>
		<link>http://realazy.org/blog/2008/03/18/pro-js-techniques-chinese-version-published/</link>
		<comments>http://realazy.org/blog/2008/03/18/pro-js-techniques-chinese-version-published/#comments</comments>
		<pubDate>Tue, 18 Mar 2008 13:55:37 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/03/18/pro-js-techniques-chinese-version-published/</guid>
		<description><![CDATA[去年跟 jjgod 一起翻译的书，《精通 JavaScript》 终于上市了。此书原名为 Pro JavaScript Techniques, 系 jQuery 之父 John Resig 所著。
这是一本没有 &#8220;hello world&#8221; 的书，在未翻译前我已经推荐过。希望窥探 JavaScript 高级应用的读者可以一读。推荐大家从网上购买，这样折扣多些。
如果你有任何想法，可以致信 projsch@gmail.com, 欢迎交流。
p.s. 最近更新不勤，一则工作忙，二则积蓄待发。自学 C 语言几月有余，略有小成。新近在看 Objective-C 和 Cocoa, 希望能开发些客户端程序。数据结构和算法依然在门外，一步一步来吧。God bless you, also me.
]]></description>
			<content:encoded><![CDATA[<p>去年跟 <a href="http://blog.jjgod.org">jjgod</a> 一起翻译的书，<strong><a href="http://realazy.org/jspro">《精通 JavaScript》</a></strong> 终于上市了。此书原名为 <a href="http://jspro.org/">Pro JavaScript Techniques</a>, 系 <a href="http://jquery.com">jQuery</a> 之父 <a href="http://ejohn.org">John Resig</a> 所著。</p>
<p>这是一本没有 &#8220;hello world&#8221; 的书，在未翻译前我已经<a href="http://realazy.org/blog/2007/01/03/pro-javascript-techniques-review/">推荐</a>过。希望窥探 JavaScript 高级应用的读者可以一读。推荐大家从网上购买，这样折扣多些。</p>
<p>如果你有任何想法，可以致信 projsch@gmail.com, 欢迎交流。</p>
<p>p.s. 最近更新不勤，一则工作忙，二则积蓄待发。自学 C 语言几月有余，略有小成。新近在看 Objective-C 和 Cocoa, 希望能开发些客户端程序。数据结构和算法依然在门外，一步一步来吧。God bless you, also me.</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/03/18/pro-js-techniques-chinese-version-published/feed/</wfw:commentRss>
		</item>
		<item>
		<title>海内网招聘前端开发工程师</title>
		<link>http://realazy.org/blog/2008/03/01/hainei-jobs/</link>
		<comments>http://realazy.org/blog/2008/03/01/hainei-jobs/#comments</comments>
		<pubDate>Sat, 01 Mar 2008 03:10:12 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[杂]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/03/01/hainei-jobs/</guid>
		<description><![CDATA[如题，这是一个在北京的工作机会。
工作职责：

使用 HTML/CSS/Javascript 开发符合 W3C 标准的网站前端页面；
使用AJAX，Flash等技术丰富网站功能，增强用户体验；
和后台工程师一起研讨技术实现方案，制定服务接口等；
积累并完善自己的前端WEB开发框架，Javascript开发框架；
积极探索并积累前端开发模式和规范。

职位要求：

本科以上学历，能熟练阅读英文技术文档；
具备良好的团队合作精神和积极主动的沟通意识；
具有强烈的进取心和求知欲，勇于挑战；
精通HTML/CSS/Javascript等前端技术，习惯于手写符合W3C标准、兼容多种浏览器的前端页面代码，而不是依赖IDE；
有Flash，ActionScript开发经验者优先；
有设计经验，熟悉Photoshop、Illustrator者优先；
计算机相关专业毕业者优先。

有意者请致信 job(a)hainei.com.
另外还招聘产品经理、研发工程师和高级研发工程师/架构师。详情见 http://hainei.com/job.
]]></description>
			<content:encoded><![CDATA[<p>如题，这是一个在北京的工作机会。</p>
<p><strong>工作职责：</strong></p>
<ul>
<li>使用 HTML/CSS/Javascript 开发符合 W3C 标准的网站前端页面；</li>
<li>使用AJAX，Flash等技术丰富网站功能，增强用户体验；</li>
<li>和后台工程师一起研讨技术实现方案，制定服务接口等；</li>
<li>积累并完善自己的前端WEB开发框架，Javascript开发框架；</li>
<li>积极探索并积累前端开发模式和规范。</li>
</ul>
<p><strong>职位要求：</strong></p>
<ul>
<li>本科以上学历，能熟练阅读英文技术文档；</li>
<li>具备良好的团队合作精神和积极主动的沟通意识；</li>
<li>具有强烈的进取心和求知欲，勇于挑战；</li>
<li>精通HTML/CSS/Javascript等前端技术，习惯于手写符合W3C标准、兼容多种浏览器的前端页面代码，而不是依赖IDE；</li>
<li>有Flash，ActionScript开发经验者优先；</li>
<li>有设计经验，熟悉Photoshop、Illustrator者优先；</li>
<li>计算机相关专业毕业者优先。</li>
</ul>
<p>有意者请致信 job(a)hainei.com.</p>
<p>另外还招聘产品经理、研发工程师和高级研发工程师/架构师。详情见 <a href="http://hainei.com/job">http://hainei.com/job</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/03/01/hainei-jobs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Bookmarklet</title>
		<link>http://realazy.org/blog/2008/02/25/bookmarklet/</link>
		<comments>http://realazy.org/blog/2008/02/25/bookmarklet/#comments</comments>
		<pubDate>Sun, 24 Feb 2008 16:04:19 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/02/25/bookmarklet/</guid>
		<description><![CDATA[按照维基的定义，A bookmarklet is an applet, a small computer application, stored as the URL of a bookmark in a web browser or as a hyperlink on a web page. 最近，它在一些新兴的网站中比较流行，比如 facebook, friendfeed. 从技术角度来看，它通常是一段来自提供方的可执行 JavaScript, 用以捕获当前网页的某些元素如标题、图片等以加强当前网页与提供方网站之间的交互。
那么，从技术角度来说，bookmarklet 有什么需要注意的呢？我个人意见如下：
首先，因为它是一段 JavaScript, 所以应该遵循普世的 JavaScript 编程原则。最重要的一点是，不要污染当前网页的命名空间，否则可能会破坏当前网页的 JavaScript. 通常，可以使用闭包来隐藏你所有的变量。同样，如果您的 bookmarklet 的 CSS 可能会入侵当前网页（很遗憾，CSS 没有命名空间，也没有类似闭包的东西，很容易就会冲突），那么请考虑将 bookmarklet 的内容放到 iframe 中去。
其次，防止函数执行后不经意的副作用，一个比较好用的贴士是，使用不返回值始终返回 undefined 的 void, 它可以接受任何参数，因此，把你的闭包放到 void [...]]]></description>
			<content:encoded><![CDATA[<p>按照维基的定义，<q cite="en.wikipedia.org/wiki/Bookmarklet">A bookmarklet is an applet, a small computer application, stored as the URL of a bookmark in a web browser or as a hyperlink on a web page</q>. 最近，它在一些新兴的网站中比较流行，比如 facebook, friendfeed. 从技术角度来看，它通常是一段来自提供方的可执行 JavaScript, 用以捕获当前网页的某些元素如标题、图片等以加强当前网页与提供方网站之间的交互。</p>
<p>那么，从技术角度来说，bookmarklet 有什么需要注意的呢？我个人意见如下：</p>
<p>首先，因为它是一段 JavaScript, 所以应该遵循普世的 JavaScript 编程原则。最重要的一点是，不要污染当前网页的命名空间，否则可能会破坏当前网页的 JavaScript. 通常，可以使用<a href="http://www.jibbering.com/faq/faq_notes/closures.html">闭包</a>来隐藏你所有的变量。同样，如果您的 bookmarklet 的 CSS 可能会入侵当前网页（很遗憾，CSS 没有命名空间，也没有类似闭包的东西，很容易就会冲突），那么请考虑将 bookmarklet 的内容放到 <code>iframe</code> 中去。</p>
<p>其次，防止函数执行后不经意的副作用，一个比较好用的贴士是，使用<del datetime="2008-02-25T03:01:48+00:00">不返回值</del>始终返回 <code>undefined</code> 的 <a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Special_Operators:void_Operator"><code>void</code></a>, 它<strong>可以接受任何参数</strong>，因此，把你的闭包放到 <code>void</code> 中是个不错的主意：</p>
<pre><code>javascript:void((function(){...})());</code></pre>
<p>最后，有一个比较恼火的问题也需要加以注意。目前世界上最流行的浏览器，IE6, 它对 bookmarklet 所能容忍的长度仅为 <strong>508</strong>!</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/02/25/bookmarklet/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mac OS 和 Emacs</title>
		<link>http://realazy.org/blog/2008/01/27/emacs-on-mac/</link>
		<comments>http://realazy.org/blog/2008/01/27/emacs-on-mac/#comments</comments>
		<pubDate>Sun, 27 Jan 2008 12:38:55 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[自由与开源]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/01/27/emacs-on-mac/</guid>
		<description><![CDATA[最近入手了一台 MacBook 061.
由于 Mac OS 身上淌着 Unix 的血液，要找到一些不用花钱的生产力工具还是很容易的。最近习惯了 GNU Emacs (以下简称 Emacs), 所以不管三七二十一，找一个来安装上再说。
才发现 Mac OS 下的 Emacs 版本如此之多。我分别尝试了 Emacs.app, Carbon Emacs 和 Aquamacs.
首先，Emacs.app 基于还在开发中的 Emacs 23，这个版本最大的改动之一就是字体的处理方式，无疑，在 Mac OS 下，三者中也是它的字体支持最好。Carbon Emacs 和 Aquamacs 都是基于 Emacs 22 的，对字体的支持不足（比如中英混排，或者对字型的选择都比较奇怪）。我对Carbon Emacs 没有什么印象，倒是因为 Aquamacs 解决一个至关重要的问题，我才不得不选择它。
如果你用过 Emacs, 你就知道它是多么依赖于各种快捷键。问题在于，MacBook 键盘右边没有 control 键。当然可以通过设置来让 command 或者 option 来充当 control 键来解决问题，但是为了一个 Emacs 而改变整个系统的键盘布局方式，有点得不偿失。而 Aquamacs 可以使得这样的设置只在 [...]]]></description>
			<content:encoded><![CDATA[<p>最近入手了一台 MacBook 061.</p>
<p>由于 Mac OS 身上淌着 Unix 的血液，要找到一些不用花钱的生产力工具还是很容易的。最近习惯了 GNU Emacs (以下简称 Emacs), 所以不管三七二十一，找一个来安装上再说。</p>
<p>才发现 Mac OS 下的 Emacs 版本如此之多。我分别尝试了 <a href="http://emacs-app.sourceforge.net/">Emacs.app</a>, <a href="http://homepage.mac.com/zenitani/emacs-e.html">Carbon Emacs</a> 和 <a href="http://aquamacs.org/">Aquamacs</a>.</p>
<p>首先，Emacs.app 基于还在开发中的 Emacs 23，这个版本最大的改动之一就是字体的处理方式，无疑，在 Mac OS 下，三者中也是它的字体支持最好。Carbon Emacs 和 Aquamacs 都是基于 Emacs 22 的，对字体的支持不足（比如中英混排，或者对字型的选择都比较奇怪）。我对Carbon Emacs 没有什么印象，倒是因为 Aquamacs 解决一个至关重要的问题，我才不得不选择它。</p>
<p>如果你用过 Emacs, 你就知道它是多么依赖于各种快捷键。问题在于，MacBook 键盘右边没有 control 键。当然可以通过设置来让 command 或者 option 来充当 control 键来解决问题，但是为了一个 Emacs 而改变整个系统的键盘布局方式，有点得不偿失。而 Aquamacs 可以使得这样的设置只在 Emacs 内生效而不影响系统：</p>
<pre><code>(setq mac-command-modifier 'control)
(setq mac-control-modifier 'alt)
(setq mac-option-modifier 'meta)</code></pre>
<p>p.s. 至于 Textmate, 先慢慢尝试一下吧。我的工作环境不可能不处理中文，Textmate 不支持中文严重降低了我去使用它的频度。</p>
<p>更新：后来又折腾一下 Emacs.app, 发现它其实也可以 remap 键位的。无疑，我马上把 Aquamacs 抛弃了。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/01/27/emacs-on-mac/feed/</wfw:commentRss>
		</item>
		<item>
		<title>opera img onload重复执行</title>
		<link>http://realazy.org/blog/2008/01/09/opera-img-onload-problem/</link>
		<comments>http://realazy.org/blog/2008/01/09/opera-img-onload-problem/#comments</comments>
		<pubDate>Wed, 09 Jan 2008 07:51:43 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2008/01/09/opera-img-onload-problem/</guid>
		<description><![CDATA[由于某些原因需要把函数直接放到 img 标签上的 onload 属性执行，比如：
For some reasons we have to execute the JavaScript function in the img tag&#8217;s attribute onload, e.g.
&#60;img onload="javascript:jsFunction();" ...
开启 Opera, CPU 狂窜到 100%……
When using Opera browser, the CPU usage is up to 100%&#8230;
原来丫会重复执行 jsFunction……只好加个变量来记录是否已经执行。
Because Opera execute jsFunction repeatedly. The solution is adding an flag variable to track the function be executed [...]]]></description>
			<content:encoded><![CDATA[<p>由于某些原因需要把函数直接放到 <code>img</code> 标签上的 <code>onload</code> 属性执行，比如：</p>
<p>For some reasons we have to execute the JavaScript function in the <code>img</code> tag&#8217;s attribute <code>onload</code>, e.g.</p>
<pre><code>&lt;img onload="javascript:jsFunction();" ...</code></pre>
<p>开启 Opera, CPU 狂窜到 100%……</p>
<p>When using Opera browser, the CPU usage is up to 100%&#8230;</p>
<p>原来丫会重复执行 <code>jsFunction</code>……只好加个变量来记录是否已经执行。</p>
<p>Because Opera execute <code>jsFunction</code> repeatedly. The solution is adding an flag variable to track the function be executed or not.</p>
<p>Google 一下并没有发现这方面的资料，所以记下来，希望能帮助碰到这个问题的人。为了表现我的国际主义精神，特翻译了一下（至于这句，就不翻了……）。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2008/01/09/opera-img-onload-problem/feed/</wfw:commentRss>
		</item>
		<item>
		<title>2008</title>
		<link>http://realazy.org/blog/2007/12/30/2008/</link>
		<comments>http://realazy.org/blog/2007/12/30/2008/#comments</comments>
		<pubDate>Sun, 30 Dec 2007 12:31:08 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[杂]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2007/12/30/2008/</guid>
		<description><![CDATA[不经意，又到了一年一度的总结和展望时间了。
2006末，在不懂MySQL, Ruby的情况下，用RoR折腾出一个十分简单的jobz board, 向世界宣布我“会”编程了。侥幸进入中国雅虎（已在8月份离职），虽大部分时间还是折腾HTML和CSS, 但也有了练习JavaScript的机会，怎么说，以前玩linux积累一些非编程但有助于了解编程的经验，在练习过程中得以入门编程，还写得真像那么回事了。
记得2007的展望是精通JavaScript，这个完成得有60%吧，对PHP和MySQL也有一定的了解。至于Ruby，没地方用，所以顶多掌握了一些概念和语法，倒是Python，用得还多点，年末用webpy和SQLite3写了一个blog程序，算是对Python入了点门。
还好，不经意间踏上了编程之路。
但一提到“编程”二字，常常让我觉得汗颜。程序者，经典公式为程序＝算法+数据结构。但是我既不懂算法，也不懂数据结构。我说我在编程（programming），实在是跟全天下的程序员（programmer）过不去，我顶多是个编码者（coder）而已。
因此，2008, 北京要举办奥运会，我要学习算法和数据结构。从而需要自补高等数学（不好意思，我是文科生 :D），也从而需要学好C语言。高数、C语言、算法和数据结构，用我党的话说，这是2008的主旋律。
如果时间充足的话，还计划使用Python做些GUI应用。计算机的精彩决不仅仅局限于web.
回顾一下年初，有些话说过了头，但基本上都履行了。虽然没法攒够钱给支持家庭，但也算是最有力度的一年了。
2007年10月，我奶奶安详辞世，享86岁。愿往者安息，生者健康，以奋斗来慰藉往者的关怀与爱护！
]]></description>
			<content:encoded><![CDATA[<p>不经意，又到了一年一度的总结和展望时间了。</p>
<p>2006末，在不懂MySQL, Ruby的情况下，用RoR折腾出一个十分简单的jobz board, 向世界宣布我“会”编程了。侥幸进入中国雅虎（已在8月份离职），虽大部分时间还是折腾HTML和CSS, 但也有了练习JavaScript的机会，怎么说，以前玩linux积累一些非编程但有助于了解编程的经验，在练习过程中得以入门编程，还写得真像那么回事了。</p>
<p>记得2007的展望是精通JavaScript，这个完成得有60%吧，对PHP和MySQL也有一定的了解。至于Ruby，没地方用，所以顶多掌握了一些概念和语法，倒是Python，用得还多点，年末用<a href="http://webpy.org">webpy</a>和SQLite3写了一个blog程序，算是对Python入了点门。</p>
<p>还好，不经意间踏上了编程之路。</p>
<p>但一提到“编程”二字，常常让我觉得汗颜。程序者，经典公式为<strong>程序＝算法+数据结构</strong>。但是我既不懂算法，也不懂数据结构。我说我在编程（programming），实在是跟全天下的程序员（programmer）过不去，我顶多是个编码者（coder）而已。</p>
<p>因此，2008, 北京要举办奥运会，我要学习算法和数据结构。从而需要自补高等数学（不好意思，我是文科生 :D），也从而需要学好C语言。高数、C语言、算法和数据结构，用我党的话说，这是2008的主旋律。</p>
<p>如果时间充足的话，还计划使用Python做些GUI应用。计算机的精彩决不仅仅局限于web.</p>
<p>回顾一下年初，有些话说过了头，但基本上都履行了。虽然没法攒够钱给支持家庭，但也算是最有力度的一年了。</p>
<p>2007年10月，我奶奶安详辞世，享86岁。愿往者安息，生者健康，以奋斗来慰藉往者的关怀与爱护！</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2007/12/30/2008/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JavaScript 数组的 uniq 方法</title>
		<link>http://realazy.org/blog/2007/12/07/uniq-method-for-js-array/</link>
		<comments>http://realazy.org/blog/2007/12/07/uniq-method-for-js-array/#comments</comments>
		<pubDate>Fri, 07 Dec 2007 09:10:11 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2007/12/07/uniq-method-for-js-array/</guid>
		<description><![CDATA[来自某个nb招聘的题目：
请给Array本地对象增加一个原型方法，它的用途是删除数组条目中重复的条目(可能有多个)，返回值是一个包含被删除的重复条目的新数组。这是我的答案：
新解
Array.prototype.uniq = function(){
    var resultArr = [],
        returnArr = [],
        i = 1,
        origLen = this.length,
        resultLen;
    function include(arr, value){
  [...]]]></description>
			<content:encoded><![CDATA[<p>来自某个nb招聘的题目：</p>
<p>请给Array本地对象增加一个原型方法，它的用途是删除数组条目中重复的条目(可能有多个)，返回值是一个包含被删除的重复条目的新数组。这是我的答案：</p>
<h2>新解</h2>
<pre><code>Array.prototype.uniq = function(){
    var resultArr = [],
        returnArr = [],
        i = 1,
        origLen = this.length,
        resultLen;
    function include(arr, value){
        for (var i=0, n=arr.length; i&lt;n; ++i){
            if (arr[i] === value){
                return true;
            }
        }
        return false;
    }
    resultArr.push(this[0]);
    for (i; i&lt;origLen; ++i){
        if (include(resultArr, this[i])){
            returnArr.push(this[i]);
        } else {
            resultArr.push(this[i]);
        }
    }
    resultLen = resultArr.length;
    this.length = resultLen;
    for (i=0; i&lt;resultLen; ++i){
        this[i] = resultArr[i];
    }
    return returnArr;
}</code></pre>
<p>这种解法在整个过程对原有数组的改变只有两次，效率比其他两种高了2个数量级左右！可<a href="http://realazy.org/lab/uniq.html">在此测试</a>三种解法的性能。</p>
<h2>旧解</h2>
<p>以下至“关于测试案例”之间皆为旧文，若阅读不顺，忽略之。</p>
<pre><code>Array.prototype.uniq_slow = function(){
    var ret = [],
        i = 0,
        j = 0;
    while (undefined !== this[i]){
        j = i + 1;
        while(undefined !== this[j]){
            if (this[i] === this[j]){
                ret.push(this.splice(j, 1)[0]);
            } else {
                ++j;
            }
        }
        ++i;
    }
    return ret;
}</code></pre>
<p>感谢猫仔提示，这道题目很容易让人产生误读。看清了题目后更新了。</p>
<p>为何用 <code>while</code> 而不是 <code>for</code>? 因为这个数组总是在变化，每次循环都得重新计算 <code>length</code>. 按理说，使用 <code>while</code> 效率会更高，尤其数组很大的时候。</p>
<p>欢迎大家交流讨论。</p>
<p>感谢 fdcn 提示，更新之。这里确实是容易犯错。</p>
<p>猜想由于强类型判断导致性能不高（可<a href="http://realazy.org/lab/uniq.html">在此测试</a>），因此此种做法未见有性能的提升（还稍微慢了一些），而且还不能传递类似 <code>[1,,,2,,]</code> 这样的数组。所以还是<a href="http://ued.taobao.com/blog/2007/11/20/job_test_explanation/">淘宝UED上的解法</a>比较科学（当然不是没有改进之处，比如不应该在 <code>for</code> 循环中声明变量）。</p>
<p>其实，这篇blog的意义在探讨如何避免无意义的消耗（比如计算 <code>length</code>）。但是鱼和熊掌不能兼得是自古之理，顾此失彼。当然，办法不是没有，比如数组的 <code>forEach</code>, <code>map</code> 方法等，可惜只有 <code>gecko</code> 浏览器才支持。</p>
<h2>关于测试案例</h2>
<p>数组是随机产生的1-100之间的整数，长度为5000，每个相同的大约重复5次。三个测试数组的元素构成是一致的。</p>
<h2>总结</h2>
<p>对数组的改变开销巨大，如果可能，尽量在不改变原有数组的情况下进行操作，如最终需要改变数组自身，可将结果赋予原有数组来操作。另外，对于 <code>length</code> 的计算，似乎效率并未受其影响。</p>
<p>啥时候我也该进补算法了，唉。软肋啊。</p>
<p><strong>推荐阅读：</strong> 王元涛同学的<a href="http://www.pkblogs.com/todwang/2007/12/javascript-uniq.html"> JavaScript 数组的 uniq 方法</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2007/12/07/uniq-method-for-js-array/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Opera下cloneNode的bug</title>
		<link>http://realazy.org/blog/2007/11/22/opera-clonenode-bug/</link>
		<comments>http://realazy.org/blog/2007/11/22/opera-clonenode-bug/#comments</comments>
		<pubDate>Thu, 22 Nov 2007 15:26:43 +0000</pubDate>
		<dc:creator>realazy</dc:creator>
		
		<category><![CDATA[JS / Dom]]></category>

		<guid isPermaLink="false">http://realazy.org/blog/2007/11/22/opera-clonenode-bug/</guid>
		<description><![CDATA[Opera, 作为 A-Grade 浏览器，在现在的前端开发中务必支持。它很优秀，很不幸，bug是每个浏览器都不可避免的问题，Opera亦难免。说说我发现的一个关于 cloneNode 的问题。
问题
假设我们有一个 Form 节点（node）的引用，姑且名之为 elForm，现在需要克隆一份，可以这么做：var elFormClone = elForm.cloneNode(true). 
在插入这份克隆到 DOM 树中后，IE, Firefox 均未发现问题。Opera会产生这样的问题：表单内的字段无法引用。比如，假设刚才我们的elForm 有一个 &#60;input name="title" ... /&#62;, 此时你无法通过 elFormClone.title 或者 elFormClone['title'] 获取它。
解决方案
使用 document.createElement 创建 form 元素，然后设置该元素的 innerHTML(感谢 MS 发明了它) 为elForm 的 innerHTML 即可：
var elFormClone = document.createElement('form');
// 设置一些elForm的原属性，有必要的话
...
elFormClone.innerHTML = elForm.innerHTML;
// 处理这个clone, 该咋办就咋办了
...
]]></description>
			<content:encoded><![CDATA[<p>Opera, 作为 <a href="http://developer.yahoo.com/yui/articles/gbs/#gbschart">A-Grade</a> 浏览器，在现在的前端开发中务必支持。它很优秀，很不幸，bug是每个浏览器都不可避免的问题，Opera亦难免。说说我发现的一个关于 <code>cloneNode</code> 的问题。</p>
<h2>问题</h2>
<p>假设我们有一个 Form 节点（node）的引用，姑且名之为 <code>elForm</code>，现在需要克隆一份，可以这么做：<code>var elFormClone = elForm.cloneNode(true)</code>. </p>
<p>在插入这份克隆到 DOM 树中后，IE, Firefox 均未发现问题。Opera会产生这样的问题：表单内的字段无法引用。比如，假设刚才我们的<code>elForm</code> 有一个 <code>&lt;input name="title" ... /&gt;</code>, 此时你无法通过 <code>elFormClone.title</code> 或者 <code>elFormClone['title']</code> 获取它。</p>
<h2>解决方案</h2>
<p>使用 <code>document.createElement</code> 创建 form 元素，然后设置该元素的 <code>innerHTML</code>(感谢 MS 发明了它) 为<code>elForm</code> 的 <code>innerHTML</code> 即可：</p>
<pre><code>var elFormClone = document.createElement('form');
// 设置一些elForm的原属性，有必要的话
...
elFormClone.innerHTML = elForm.innerHTML;
// 处理这个clone, 该咋办就咋办了
...</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://realazy.org/blog/2007/11/22/opera-clonenode-bug/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
