<?xml version="1.0" encoding="UTF-8"?><rss version="2.0">
    <channel>
        <title>w3ctech</title>
        <link>http://w3ctech.com/rss</link>
        <description>w3ctech</description>
        <language>en</language>
                <item>
            <title>[转载至图灵社区]对话《JavaScript高级程序设计》作者 Nicholas C. Zakas（中文版）</title>
            <link>http://www.w3ctech.com/p/1203</link>
            <guid>http://www.w3ctech.com/p/1203</guid>
            <category>行业快报</category>
            <description><![CDATA[ <a href="http://w3ctech.com/b/wp-content/uploads/2012/05/zakas.jpg"><img src="http://w3ctech.com/b/wp-content/uploads/2012/05/zakas.jpg" alt="Nicholas C. Zakas" title="Nicholas C. Zakas" width="500" class="alignnone size-full wp-image-1206" /></a>
以下内容转载至图灵社区，是图灵社区根据对《JavaScript高级程序设计》作者 Nicholas C. Zakas的采访原文翻译。

很高兴收到你的邮件，而且听说我的书那么受欢迎也很开心。以下是对问题的回答。

<strong>Q1：对各种JavaScript库的优点和缺点一直存在很多争论。在您看来，开发人员应该怎么选择合适的库？</strong>

Zakas：在选择JavaScript库的时候，有几个非常重要的方面要考虑。首先，就是时间问题，也就是你的项目多长时间必须做完？如果时间很短，那最好选择你最熟悉的JavaScript库。如果时间不那么紧迫，那你可以研究一下别的库。此时，必须要回答几个问题。还有谁在使用这个JavaScript库？这个库有人在不断完善吗？这个库的文档是否完整详细？这个库的背后有没有一个社区，假如你遇到了问题，能不能获得该社区的支持？是否容易找到具有使用这个库经验的工程师？这个库能不能解决你的所有问题，还是只能解决其中一部分？所有这些都是在选择某个JavaScript库时需要考虑的重要因素。

<strong>Q2：你对HTML5的未来怎么看？现在的宣传是不是太过分了？</strong>

Zakas：HTML5对Web发展是一件好事儿。但不好的是，一些外行的非技术人员，不分青红皂白地给很多无关的东西都扣上”HTML5“的帽子，这才搞得HTML5这个概念满天飞。这与几年前“Ajax”的情况非常相似。从某种角度看，确实宣传上有点过了，仿佛HTML5会彻底改变每个人的生活。事实并非如此。HTML5的意义在于为开发人员提供了更多的工具，利用这些工具能够创建更有吸引力的用户体验。

<strong>Q3：看来，Mobile Web（移动互联网）开发会成为下一行业焦点，你觉得呢？</strong>

Zakas：移动互联网开发已经是焦点了。今天，谁不关注移动用户，谁就要被时代抛弃。移动互联网可不是昙花一现，它将是一个时代。如果你真是在开发Web应用，那么就必须考虑移动体验，否则就会让别人让抢占先机。

<strong>Q4：现在有很多基于JavaScript改进的语言，比如Dart、 CoffeeScript，等等。你认为JavaScript今后的路会朝着哪方面发展呢？是更加类似于JVM这种的中间层，还是仍然维持一个强大灵活的编程语言存在？或者说，对于专注于JavaScript的前端工程师来说，是否应该投入大精力去研究和使用CoffeeScript这种语言来简化工作，而不是纠结于JavaScript本身可能的繁复解决方案呢？</strong>

Zakas：我没觉得JavaScript有一天只会被当成一个中间层。Dart和CoffeeScript很引人关注，这说明开发人员可能更希望JavaScript能多适应一些应用场景。最终，我想JavaScript会博采众长，吸纳其他语言中更流行的范式，从而使语言核心更完善。但我不认为将来的Web开发人员会只用Dart或CoffeeScript或者其他能编译为JavaScript的语言写代码。

<strong>Q5：你觉得Node.js怎么样？它会在服务器端开发中发挥重要作用吗？将来，Web前、后端开发真能只用一种语言来做吗？</strong>

Zakas：我认为Node.js对未来Web应用的重要性难以估量。开发人员一直在寻找一个可以替代PHP的方案，以便更迅速、更容易地介入服务器端开发。而在服务器上写JavaScript代码就是一种方案。Node.js不只是一个服务器端的JavaScript引擎，它更为高性能、高扩缩的Web应用提供了一个解决方案。正因为如此，很多JavaScript爱好者可能会转型为后端开发工程师。这样一来，前、后端的沟通会更加顺畅、直接，无论是面对面沟通，还是通过代码交流。

<strong>Q6：请问用JavaScript实现一些实用算法——比如压缩ZIP格式，是否可行？</strong>

Zakas：不仅可行，而且已经有人做到了！斯图尔特•奈特利（Stuart Knightley）就创建了一个叫JSZip（http://stuartk.com/jszip/）的项目，让我们能够用JavaScript来压缩文件。我认为未来还会出现很多类似实用算法的JavaScript实现。在实现某些复杂的算法时，可以不使用JavaScript，但这种可能性是永远存在的。

<strong>Q7：是否有必要强调JavaScript编码风格的一致性？在构建一个大型B/S系统时，如何以最佳方式划分HTML、CSS和JavaScript人员的职责？</strong>

Zakas：我觉得任何语言都需要强调编码风格的一致性。只要是团队开发，每个人都以相同方式编写代码就是至关重要的。这样大家才能方便地互相看懂和维护对方的代码。在一个团队中，HTML、CSS和JavaScript的编码风格都应该保持一致。这也是我为什么要写《可维护JavaScript》（Maintainable JavaScript）这本新书的原因，这本书里就解释了作为团队一分子，应该怎么写JavaScript。不过，同样的原则也适用于任何语言。

<strong>Q8：异步、回调编程方式正被广泛使用，但很容易出现复杂的回调函数。虽然有deferred和promise这些模式，但对开发人员还是不小的挑战，请问未来是否有可能在语言层面有所改观？</strong>

Zakas：经常有人提出建议，希望添加一些语言特性来简化异步编程工作。JavaScript语言层面到底会不会增加这种特性，现在还说不好，只能拭目以待。目前，有很多人认为回调和异步编程值得提倡，但我不那么认为（这句话这样译，对否？——译者注）。如果几乎所有方法都需要一个回调，那会导致代码很难调试和维护。我确实希望不久的将来，JavaScript能在语言层面给出一些解决方案。

<strong>Q9：今天，你涉足Web开发已超过15年，你当初怎么就会选择这个行业呢？能否给中国的开发人员一些职业规划方面的建议（有朝一日也能成为像你一样的专家）？</strong>

Zakas：我进入这一行，纯属误打误撞。上大学的时候，我的专业是计算机科学，但Pascal和C语言这些课让我感觉很无聊。我讨厌整天坐在黑底白字的电脑屏幕前。当时，我想跟高中同学保持联系，有人告诉我有一种新技术，说是叫Web。于是 ，1996年我在AOL上建立了自己的第一个网页，然后把网址发给同学，以便他们知道我的近况。我还想知道大家希望通过这个网页了解点其他什么情况，结果维护这个网页就成了我的业余工作。我不断研究、尝试，在此期间自学了JavaScript。结果大学一毕业，我就知道自己得在互联网行业谋份差事了。

我对Web开发人员最大的建议就是：热爱你的工作。热爱跨浏览器开发带来的挑战、热爱互联网技术的种种异端，热爱业内的同行，热爱你的工具。互联网发展太快了，如果你不热爱它的话，不可能跟上它的步伐。这意味着你必须多阅读，多动手，保证自己的才能与日俱增。下了班也不能闲着，要做一些对自己有用的事儿。可以参与一些开源软件的开发，读读好书，看看牛人的博客。经常参加一些会议，看看别人都在干什么。要想让自己快速成长，有很多事儿可以去做，而且付出一定会有回报。

<strong>Q10：迄今为止，你已经写了4本JavaScript书。你怎么会想起来写这些书呢，眼下还有没有写书的计划？</strong>

Zakas：我从来没有真正有过写书计划。我第一份工作只干了8个月就下岗了（因为公司散伙了）。这就是我当时的处境，大学毕业才8个月，而且又失了业。我感觉真正的学习才刚刚开始。于是我就给自己找事儿做，也就是把以前做过的事儿都写出来。写一篇，就在我的网站（http://nczonline.net）上贴一篇。然后告诉以前的同事都来看。一个朋友回信说：“嘿，你写得非常好，为什么不给杂志投稿呢？“于是，我就上网找到几个征稿的在线杂志。第一篇文章发表在DevX，后来又有几篇投给了WebReference。我的文章很受好评，因此我也非常乐意接着写下去。后来有一天，我看了WebReference的一篇文章，说有另一位作者，她把自己写过的文章集合起来出了一本书。我心想：“等一下，把文章集合在一块就可以出一本书？这事儿我也能干呐！”于是，我就给自己定了一个目标，坚持写，写本书出来。这就是后来的《JavaScript高级程序设计》（Professional JavaScript for Web Developers）。

写另外三本书则隔了很久。《Ajax高级程序设计》（Professional Ajax）实际上是Wrox的编辑策划的一个选题，因为我出版过一本书，所以他就找到了我。一开始我拒绝了，因为觉得可写的东西还不够多。但他坚持让我写，我最终还是应承下来。我很高兴又写了这本书，因为它后来也非常受欢迎。《高性能JavaScript》（High Performance JavaScript）是通过雅虎出版的，当时是雅虎内部人员联系我写的。显然，另外一些人也希望写点相关的东西放在书里，但当时大家都没有时间动笔。所以，我就在他们已有成果的基础上做些修改，改到自己觉得舒服为止。后来又找了几位合著者，共同完成了这本书。

《可维护JavaScript》（Maintainable JavaScript）是我最近才出版的一本书，内容源于6年前的一次演讲。我一直都认为这个主题很值得写，写成一本书都没问题，但就是不知道从何写起。去年12月的一个周六，我一觉醒来，突然觉得才思泉涌，满脑子都是写这本书的想法。我干脆起床，在电脑前坐了一整天，终于把脑子里的想法都落实成了文字。那一天，我写了大约45页。12月份剩下的时间我都花在了写书上，结果不到一个月就写完了这本书。

目前，我还没有再写书的计划。我准备先搁笔一段时间，因为最近我一直都在写，都连续写了一年多了。确实有几个主题值得写书，但在此之前，我得等待灵感爆发的那一刻。

<strong>Q11：能否谈谈你的公司Nicholas C. Zakas Consulting？很多中国程序员也有创业的梦想，能分享一下你的经验吗？</strong>

Zakas：我的咨询公司实际上只有我一个人。我依靠自己的经验为互联网公司提供前端技术建议，包括性能评估、架构设计与评审、推行最佳实践等专业Web开发公司可能需要的各方面帮助。这为我积累了宝贵的经验，让我得以接触各式各样的公司，结识他们的团队，了解他们正在做哪些激动人心的事情。

对于想自己开公司的人，我可以给出的最好建议，就是要有自知之明。你必须得知道一些事儿，比如自己开公司没有工资，有时候一连几个月可能都没有收入。自己开公司要应对很多风险，如果你后面有家人支持，可能风险会小得多。我创业的时机很好，因为我还没有成家，也没有其他经济负担，所以我可以承受创业不成功再回头找工作的风险。但并不是所有人都像我一样。如果你真心喜欢做点什么，坚信朝哪个方向努力一定成功，觉得自己能承受得了风险，那就不要犹豫。

<strong>Q12：你经常上哪些在线社区？请给中国读者推荐一些有用的在线资源。</strong>

Zakas：我最近没怎么上网上社区，我是Twitter控，关注那些能告诉我Web技术发展走向的人。我很愿意多花时间在线下跟人交流，比如在公司里，或者在会场上，这样可以了解到最前沿的东西。

我泡GitHub的时间非常多，有时候是看别人的项目，有时候是弄自己的。我在上面经常看到有人讨论代码该怎么写，这样写是为什么之类的讨论，都非常精彩。而通过看别人的代码真的能学习到很多东西。在碰巧遇见自己有感觉的项目，而又认为自己可以提供一些不同思路时，我甚至会为这些项目贡献一些代码。

图灵社区原文地址：<a href="http://www.ituring.com.cn/article/1791" title="http://www.ituring.com.cn/article/1791">http://www.ituring.com.cn/article/1791</a> ]]></description>
            <pubDate>2012年05月16日</pubDate>
        </item>
                <item>
            <title>webapp 开发进阶</title>
            <link>http://www.w3ctech.com/p/1154</link>
            <guid>http://www.w3ctech.com/p/1154</guid>
            <category>JavaScript</category>
            <description><![CDATA[ <strong>App 图标</strong>
苹果从IOS4.2开始mobile safari就开始支持把网页保存至主屏，从而使得用户可以方便的从主屏的快捷方式进入webapp，而通过苹果提供给我们的API我们可以使得 webapp 像原生app 一样拥有自己的icon。
<pre rel="HTML" class="prettyprint">
&lt;link rel="apple-touch-icon" href="/custom_icon.png"/&gt;
&lt;link rel="apple-touch-icon" href="touch-icon-iphone.png" /&gt;
&lt;link rel="apple-touch-icon" sizes="72x72" href="touch-icon-ipad.png" /&gt;
&lt;link rel="apple-touch-icon" sizes="114x114" href="touch-icon-iphone4.png" /&gt;
</pre>
对于多设备的多分辨率，苹果提供了sizes这个属性。如果不指定这个属性，默认 sizes 会是57 * 57。
对应 apple-touch-icon 苹果还有另外一个属性 apple-touch-icon-precomposed ，他们的不同之处在于使用 apple-touch-icon-precomposed 属性的时候，苹果不会给桌面图标加一个高光效果。

<strong>App StartUp Image</strong>
苹果 IOS 3.0以后就支持 Startup Image 属性，webapp 在苹果手机上可以给网页指定StartUp Image，使得当webapp从主屏打开时，设为StartUp的封面图片会首先出现，类似原生app。但是苹果对于指定的图片有些限制，必须满足大小。对于 iphone 和 itouch 图片的尺寸只能是 320 x 460 ，其他大小的都无效。但是你可以通过sizes 来进行多设备适配。
<pre rel="HTML" class="prettyprint">
&lt;link rel="apple-touch-startup-image" href="/startup.png"&gt;
&lt;!-- for iPhone Retina Display high 适配高分辨率iPhone --&gt;
&lt;link rel="apple-touch-startup-image" sizes="640x960" href="img/splash-screen-640x960.png" /&gt;
&lt;!-- for iPad Landscape 适配iPad横屏 --&gt;
&lt;link rel="apple-touch-startup-image" sizes="1024x748" href="img/splash-screen-1024x748.png" /&gt;
&lt;!-- for iPad Portrait 适配iPad竖屏 --&gt;
&lt;link rel="apple-touch-startup-image" sizes="768x1004" href="img/splash-screen-768x1004.png" /&gt;</pre>
<strong>隐藏地址栏</strong>
IOS 下想要进入全屏模式，并且不再出现地址栏和屏幕底下的操作菜单，可以通过 apple-mobile-web-app-capable 属性来实现
<pre>&lt;meta name="apple-mobile-web-app-capable" content="yes" /&gt;</pre>
目前以上和保存到主屏相关的大多属性都是iPhone only，如果你感兴趣<a title="ConfiguringWebApplications" href="https://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html" target="_blank">这里</a>有更详细的说明。

<strong>Display 显示</strong>
为了适应网页在设备屏幕上的显示,需要通过设置 viewport 的大小来使得网页更适应在设备上阅读。如果仅仅是适应阅读，下列代码第一条就能满足，如果要防止用户在使用webapp时的放大手势操作和缩小手势则需要通过设置user-scalable、其初始化的放大倍数、最大放大倍数和最小缩小倍数来实现。
<pre rel="HTML" class="prettyprint">
&lt;meta name="viewport" content="width=device-width" /&gt;
&lt;meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" /&gt;</pre>
<strong>CSS 渲染</strong>
在IOS 或是 andriod上系统自带的都是webkit内核的浏览器，比起在web端饱受微软IE6之苦的程序员来说，webapp确实看似美好了许多。然而毕竟手机端不比PC端，许多渲染小细节不注意，往往会导致这个页面的顿挫感甚至crash。有几个CSS属性值得注意：
<pre class="prettyprint">
-webkit-box-shadow
-webkit-border-radius
-webkit-gradient</pre>
在webapp 上，虽说button渐变色，圆角，阴影不再难实现，但是对于CSS渲染来说，这些属性都是高耗品。在项目中对大片的元素使用圆角，和大片元素使用阴影能够明显的感觉到页面滚动的顿挫感。然而过于重度使用绝对定位或是相对定位也会使得浏览器不堪重负而崩溃。这点在mobile safari 上体现的非常明显，所以也尽量少使用绝对定位来完成布局。
<pre class="prettyprint">
position:absolute;
position:relative;</pre>
<strong>CSS3 动画</strong>
webapp 相比传统wap2.0 页面，多媒体和交互上面都有着传统wap远不能及的表现力。native app 虽然在这点上表现十分抢眼，却不如webapp的多平台性。为了迎合这一趋势 CSS3 动画都被各大浏览器厂商支持的很好。例如 transform 和transition，使用这些CSS属性做动画时，值得我们注意的是应该尽量利用3D模式，使得浏览器能够通过启用硬件加速使得动画变得更加流畅。而在项目过程中偶尔碰到动画过程中的动画闪白可以通过设置backface-visibility 来解决。
<pre class="prettyprint">
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;</pre>
<strong>Touch Event 触摸事件</strong>
在web端，前端开发绑定点击事件固然是click事件，而手机端系统也为我们提供了一些事件来表示手机的操作事件分别是touchstart、touchmove、touchend，这些个事件有点类似web的mousedown、mousemove、mouseup,可惜的是成熟的web端已经有click来代表这三个事件的组合，而mobile端没有，加之手机端使用click 有一个莫名的300ms 等待时间。于是乎，很多聪明的开发者都开始使用自定义的 tap 事件。简单的封装逻辑无非就是以下这些：1、监听touchstart事件；2、在touchstart事件发生时，监听touchmove事件。2、根据touchmove 事件是否产生来断定是否在touchend的时候执行事件指定的回调函数。如果你觉得这样太麻烦了，没有关系，可以不用重复造轮子，试试 mike brook 的<a title="thumbs.js" href="http://mwbrooks.github.com/thumbs.js/" target="_blank">thumbs.js</a>也不错。还有一点值得我们注意的是在手机上，a 标签被点击时会有一个难看的点击阴影（在andriod上尤其难看）这个阴影可以通过改变CSS 属性 -webkit-tap-highlight 来去掉。
<pre class="prettyprint">
-webkit-tap-highlight:rgba(0,0,0,0);</pre>
<strong>Localstorage 本地存储</strong>
对于 webapp 来说，本地存储可以配合appCache使得webapp和native app一样具有离线浏览的功能，如何利用好本地存储也确实是一件非常值得研究的事情。而目前浏览器的本地存储都只支持字符串的直接存储，虽然也是key/value性质，但是总会觉得有些不便。项目过程中如果使用localstorage，能像用永久变量一样方便自如,还是需要开发者自行封装，虽然很多浏览器以及提供了JSON对象的stringfy和parse，单仍有少数浏览器不支持，如android 2.1。可以试试lawnchair，一个简单的json 存储器，大小只有5k，项目地址http://westcoastlogic.com/lawnchair/

<strong>缓存</strong>
单独拿出来说缓存其实没有什么意义，但对于把用户群瞄准为高端iPhone用户的开发者还是应该了解，在iPhone的 mobile safari中，缓存是有限制的，在IOS 3.X 版本mobile safari不能缓存超过15KB的单个文件，在IOS4中这个限制是25KB。 如果想最大利用缓存的同学可能要权衡一下单个文件的大小还是 HTTP 请求数了。相比之下android的限制要小得多, android 单个文件的缓存限制为2MB。

<strong>Iscroll 4</strong>
滚动组件，虽然IOS5 已经支持
<pre class="prettyprint">
position:fixed;
overflow:scroll;
-webkit-overflow-scrolling: touch;</pre>
但是对于andriod 还遥遥无期的样子，而Iscroll 4目前是很多固定滚动的良好解决方案，连microsoft metro的演示demo和apple官方都在使用Iscroll 4。

<strong>JS类库</strong>
jquery大名鼎鼎，做前端应该都听过，而在mobile 端再用会显得有些太重了，一大堆兼容IE的代码。虽然使用方便，但是仍然是不推荐的。其实mobile js library设计时有不少都受到了jquery的影响，他们提供的接口几乎一致，比如zepto、xuijs、jqmobi 这些都是基础类库，不带ui组件。如果希望有ui组件的同学可以看看jqtouch 和 sencha touch。我推荐的这些类库有些是只对webkit核心浏览器设计的，毕竟目前这些(andriod 和iPhone)在智能手机里占得比重比较大。
<blockquote>zepto：https://github.com/madrobby/zepto
sxuijs：http://xuijs.com/
jqmobi: http://www.jqmobi.com/</blockquote>
参考：
<a title="苹果官方开发者网站关于webapp的配置" href="https://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html" target="_blank">苹果官方开发者网站关于webapp的配置</a>
<a title="debugging-mobile" href="http://westcoastlogic.com/slides/debug-mobile/" target="_blank">debugging-mobile</a>
<a title="mobile-browser-cache-limits" href="http://www.yuiblog.com/blog/2010/06/28/mobile-browser-cache-limits/" target="_blank">mobile-browser-cache-limits</a> ]]></description>
            <pubDate>2012年05月07日</pubDate>
        </item>
                <item>
            <title>解码jQuery系列5 – OOP与jQuery</title>
            <link>http://www.w3ctech.com/p/1183</link>
            <guid>http://www.w3ctech.com/p/1183</guid>
            <category>JavaScript</category>
            <description><![CDATA[ 译者注：本系列文章由石川创作，李松峰翻译，w3ctech.com首发，图灵社区转载。

“OOP与jQuery”是“解码jQuery”系列中的一个子系列，主要讨论 jQuery 的内部构成及相关的OOP（Object Oriented Programming，面向对象编程）概念。

在这篇文章中，我们会讨论工厂设计模式，也是jQuery核心中使用的一种设计模式。

1.创建对象

“四人帮”的名著Design Patterns: Elements of Reusable Object-Oriented Software（《设计模式》，http://en.wikipedia.org/wiki/Design_Patterns）把设计模式分为三类：

创建模式：创建对象的各种方式；
结构模式：组合各种对象以实现新的功能；
行为模式：对象之间互操作的方式。

工厂模式属于创建模式，顾名思义，工厂就是创建对象的。

我们先来看一看创建对象的最常见模式。好，以下代码创建了一个包含几个方法的对象。

<pre rel="JavaScript" class="prettyprint">
var taskManager = {};
taskManager.update = function() {
console.log("update");
}
taskManager.read = function() {
console.log("read");
}
</pre>
如果想通过taskManager创建一个新的任务对象，而且是基于不同的类型分别调用update和read方法，那可以这样做：
<pre rel="JavaScript" class="prettyprint">
var type = "update";
var task;
if (type === 'update') {
task = new taskManager.update();
}

if (type === 'read') {
task = new taskManager.read();
}
</pre>
可是，如果有10种不同的任务，这样做就太麻烦了。因此，就产生了工厂方法模式。

2.工厂方法模式

为了简化创建对象的工作，可以在taskManager中创建一个工厂方法：
<pre rel="JavaScript" class="prettyprint">
taskManager.factory = function (typeType) {
return new taskManager[typeType];
}
</pre>
有了这个方法，就可以像下面这样创建对象了：
<pre rel="JavaScript" class="prettyprint">
task = new taskManager[type];
</pre>
3.jQuery中的工厂方法

在jQuery的core.js中，就有一个类似的创建对象的工厂方法：
<pre rel="JavaScript" class="prettyprint">
var jQuery = function( selector, context ) {
// jQuery对象实际上就是一个“增强版的”init构造函数
return new jQuery.fn.init( selector, context, rootjQuery );
}
</pre>
使用这种方法的原因很简单，jQuery不知道用户会传入什么样的选择符，或许是标签名，如$('p')；ID，如 $('#main') ，或者类，如 $('.item')。因此，这个方法适合创建类似但事先又不知其具体类型的对象。

这里有一篇文章，叫Essential JavaScript Design Patterns For Beginners, Volume 1（http://addyosmani.com/resources/essentialjsdesignpatterns/book/），讨论了什么时候该用工厂模式，什么时候不该用工厂模式。

<h2>系列其他文章</h2>
<ul>
    <li><a href="http://w3ctech.com/p/935" title="解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn" target="_blank">解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn</a></li>
    <li><a href="http://w3ctech.com/p/881" title="解码jQuery系列3 – 原型" target="_blank">解码jQuery系列3 – 原型</a></li>
    <li><a href="http://w3ctech.com/p/843" title="解码jQuery系列2 – 对象" target="_blank">解码jQuery系列2 – 对象</a></li>
    <li><a href="http://w3ctech.com/p/812" title="解码jQuery系列1 - 变量和函数" target="_blank">解码jQuery系列1 - 变量和函数</a></li>
</ul> ]]></description>
            <pubDate>2012年05月07日</pubDate>
        </item>
                <item>
            <title>动态修改script标签中的src属性存在的问题</title>
            <link>http://www.w3ctech.com/p/1141</link>
            <guid>http://www.w3ctech.com/p/1141</guid>
            <category>前端技术</category>
            <description><![CDATA[ <p>今天某个同事遇到一个诡异的问题，问题描述如下：</p>

<p><strong>需求</strong>：通过脚本动态修改script标签的src来载入一段外部脚本并执行<br /><strong>实现方式(#1)</strong>：</p>

<pre rel="JavaScript" class="prettyprint">
&lt;script type="text/javascript" id="external-script"&gt;
&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    document.getElementById('external-script').src='url2';
&lt;/script&gt;</pre>

<p><strong>url2的内容如下</strong>：</p>

<pre rel="JavaScript" class="prettyprint">
alert('I am dynamic');
</pre>

<p><strong>结果</strong>：</p>

<ul><li>Chrome: 什么事都没发生（没有请求url2）</li>
<li>Firefox: 什么事都没发生（没有请求url2）</li>
<li>IE9：什么事都没发生（请求url2但不执行url2的脚本）</li>
<li>IE(6,7,8): I am dynamic(请求并执行了url2的脚本)</li>
</ul><p>注意实现方式中，第一段的script标签中间是有内容的（空格、换行符以及回车符）。</p>

<p>如何来解释这个问题呢？要解释这个问题，我们来看两个变种的例子，第一个例子（明确内联内容)，如下所示（#2）：</p>

<pre rel="JavaScript" class="prettyprint">
&lt;script type="text/javascript" id="external-script"&gt;
alert('I am inline');
&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    document.getElementById('external-script').src='url2';
&lt;/script&gt;
</pre>

<p>结果如下：</p>

<ul><li>Chrome: I am inline（没有请求url2）</li>
<li>Firefox: I am inline（没有请求url2）</li>
<li>IE9：I am inline（请求url2但不执行url2的脚本）</li>
<li>IE(6,7,8): I am inline I am dynamic(请求并执行了url2的脚本)</li>
</ul><p>再来看看第二个变种的例子(#3)：</p>

<pre rel="JavaScript" class="prettyprint">
&lt;script type="text/javascript" id="external-script" src="url1"&gt;
    alert('I am inline script');
&lt;/script&gt;
&lt;script type="text/javascript"&gt;
    document.getElementById('external-script').src='url2';
&lt;/script&gt;
</pre>

<p>其中url1的内容如下：</p>

<pre rel="JavaScript" class="prettyprint">
alert('I am url1');
</pre>

<p>结果如下：</p>

<ul><li>Chrome: I am url1（没有请求url2）</li>
<li>Firefox: I am url1（没有请求url2）</li>
<li>IE9：I am url1（请求url2但不执行url2的脚本）</li>
<li>IE(6,7,8): I am url1 I am dynamic(请求并执行了url2的脚本)</li>
</ul><p>首先这里肯定的是src属性是修改成功的，可以通过看dom的变化看到src已经设置进去了。这个时候我们比对这三个例子，思考几十秒。分析下这三个例子，其实#2和#1是一样的，这里用#2是为了说明#1中的空格、换行符以及回车符会被浏览器认为是内联的脚本。通过比对#2和#3，是不是会让你想到什么？没错，我们第一个会想到的就是：<em>当script标签既有src属性又有内联脚本的时候浏览器该如何处理？</em> ， 先来解释这个问题。</p>

<p>一谈到浏览器应该怎样处理，就不得不翻出各种宝典，这次不再是葵花宝典了，而是九阴真经(<a href="http://www.w3.org/TR/1999/REC-html401-19991224/interact/scripts.html#h-18.2.4" target="_blank">W3C的HTML4标准</a>)，标准中关于script标签的src部分有如下一段话：</p>

<blockquote>
  <p>If the src attribute is not set, user agents must interpret the contents of the element as the script. If the src has a URI value, user agents must ignore the element’s contents and retrieve the script via the URI</p>
</blockquote>

<p>上面这段话的意思就是说：<em>如果src没有设置，那么就执行内联脚本，如果src设置了浏览器就必须忽略内敛脚本而要去请求src指定的url的内容</em></p>

<p>这解释了为什么#3中标准浏览器（甚至IE6，7，8）都没有执行内联脚本（因为src设置了url1）。</p>

<p>搞清楚了这个基础问题之后，接下来问题就定位到了<em>动态修改script的src属性的时候浏览器如何处理？</em> ，从结果来看，标准的浏览器都没有去请求url2（更改src无效），这回IE6，7，8终于犯傻了。当然了，咱们也不能随随便便说人家犯傻，要拿出证据，这个时候继续拿出九阴真经<a href="http://www.w3.org/TR/2012/WD-html5-20120329/the-script-element.html#the-script-element" target="_blank">W3C的HTML5标准</a>，其中有这样一句话：</p>

<blockquote>
  <p>Changing the src, type, charset, async, and defer attributes dynamically has no direct effect; these attribute are only used at specific times described below.</p>
</blockquote>

<p>意思就是说：<em>修改src是没用的，对src的处理只会在特定的时候进行（个人猜测就是第一次看到这个属性的时候浏览器会去做相应处理，之后就无视它了）。</em></p>

<p>好了，这下真相大白了：这解释了为啥#3和#1中除了IE6，7，8之外其他浏览器都没有去请求url2（IE9请求了，但没执行），而且实验发现IE6，7，8对动态修改src都会做请求执行处理。</p>

<p>最后，这个故事至少告诉我们：写script标签的时候千万别手贱打回车。</p>

<p>参考文档：</p>

<ul><li><a href="http://www.w3.org/TR/2012/WD-html5-20120329/the-script-element.html#the-script-element" target="_blank">HTML5标准文档</a></li>
<li><a href="http://www.w3.org/TR/1999/REC-html401-19991224/interact/scripts.html#h-18.2.4" target="_blank">HTML4标准文档</a></li>
</ul> ]]></description>
            <pubDate>2012年04月27日</pubDate>
        </item>
                <item>
            <title>Qatrix，国产超轻量级高性能的JavaScript框架</title>
            <link>http://www.w3ctech.com/p/1132</link>
            <guid>http://www.w3ctech.com/p/1132</guid>
            <category>行业快报</category>
            <description><![CDATA[ <img src="http://ww2.sinaimg.cn/bmiddle/66a52eefgw1ds1i551nkdj.jpg" alt="Qatrix" />

Qatrix是一个简单易用，代码优美，同时专注于高性能应用开发的超轻量级JavaScript框架。这是在社交网站Catfan喵友成立两周年之际发布的一个开源新项目。是由其创始人黎言卓在开发<a href="http://catfan.me">Catfan</a>和<a href="http://mu6.me">Mu6</a>过程中，经过知识不断积累和研究，独立设计和开源出来的项目。

Qatrix具有以下几个特点：

硬件加速的动画效果
动画效果基于CSS3 transition，使用native code处理，并具备硬件加速特性，比以往单纯基于JavaScript处理的框架更加流畅，显著提升页面的视觉效果。这也是目前首个支持这种特性的完整JavaScript框架。

高性能代码
支持CSS3和HTML5的特性，专为高性能做前提而优化和设计，执行效率平均比其它JavaScript框架高50%以上。

易学易用
命名规则简单，多数和jQuery类似，开发者不需要记忆和理解太多新的概念就能轻松上手。

麻雀虽小五脏俱全
只有4.7KB的文件大小（gzipped），包含了多种元素选择器，DOM，AJAX，Cookie，基于硬件加速的动画处理，事件处理，缓存系统等足够满足大部分应用开发的需要的60+个功能。不会显著增加页面载入的时间。

良好的兼容性
兼容IE6-IE10，Chrome，Firefox，Safari，Opera等大部分主流浏览器。

基于最宽松的MIT开源协议，任何人都可以免费使用。

Qatrix项目之前已经吸引了一批国外开发者的关注和讨论，经过社区反馈和多次版本的频繁改进和修复后，目前公开发布出首个稳定版本。目前在GitHub的关注数也在不断上升中。

Qatrix目前托管在GitHub上<a href="http://github.com/qatrix/Qatrix">http://github.com/qatrix/Qatrix</a>
官方网站：<a href="http://qatrix.com">http://qatrix.com</a>
API文档：<a href="http://qatrix.com/doc">http://qatrix.com/doc</a>
性能测试：<a href="http://qatrix.com/benchmark">http://qatrix.com/benchmark</a> ]]></description>
            <pubDate>2012年04月25日</pubDate>
        </item>
                <item>
            <title>更加直观地了解hasLayout和BFC</title>
            <link>http://www.w3ctech.com/p/1101</link>
            <guid>http://www.w3ctech.com/p/1101</guid>
            <category>前端技术</category>
            <description><![CDATA[ 网络上有很多关于hasLayout和BFC相关的文章，但是大部分都显得有些晦涩难懂。所以想用一些比较直观的例子来说明hasLayout和BFC给平时的布局带来的影响。
<h2>基础知识</h2>
在讲hasLayout和BFC之前，先简单地过一下元素布局的一些基本知识。

元素本身的布局方式可以从display上表现出来
<ul>
	<li>block，对应块级元素</li>
	<li>inline，对应行内元素</li>
	<li>inline-block</li>
	<li>none</li>
</ul>
当然，还有更多的一些属性，我们只提及主要部分。

块级元素，在浏览器中通常是垂直布局，然后可以用margin来控制块级元素之间的间距，并列和嵌套的块级元素都存在外边距，也就是margin合并的问题。

而行内元素是以水平的方式布局，垂直方向的margin，padding都是无效的，并且设置的宽高也是无效的。

BFC的全名是block formatting context，转成中文就是块级元素格式上下文，听起来有些别扭，字面上的意思大概就是一个元素的布局上下文类型。

而大家应该对hasLayout已经很熟悉了，更多可能是因为IE5.5/6/7上一些奇怪的bug（还有处于quirks模式下的IE8）。

BFC和hasLayout是作为元素的一种隐藏属性存在，<del datetime="2012-03-20T07:22:37+00:00">并且一旦触发之后就不可逆转</del>。他们之间有很多共同点。（注：没有办法设置hasLayout=false， 除非把一开始那些触发hasLayout的CSS属性去除，此处是我没有表达好，谢谢@<a href="http://weibo.com/itapir" target="_blank">貘吃馍香</a>指正）
<h2>共同点</h2>
<h2>1.不和浮动元素重叠</h2>
如果一个浮动元素后面跟着一个非浮动的元素，那么就会产生一个覆盖的现象，很多自适应的两栏布局就是这么做的。

这里我们使用<a href="http://msdn.microsoft.com/en-us/library/bb250481%28VS.85%29.aspx" target="_blank">msdn上的一个例子</a>，来说明haslayout和BFC对这个情况的影响。
<pre class="prettyprint">&lt;div style="float:left; border: 2px solid red"&gt; 123&lt;/div&gt;
&lt;span style="border: 2px solid blue"&gt;
     The quick brown fox jumped over the lazy dog's back.
     The quick brown fox jumped over the lazy dog's back. 
     The quick brown fox jumped over the lazy dog's back.
     The quick brown fox jumped over the lazy dog's back. 
     The quick brown fox jumped over the lazy dog's back.
&lt;/span&gt;​</pre>
我们可以看到，文字环绕着浮动元素进行布局。

<img class="alignnone" title="文字环绕浮动元素" src="http://i.msdn.microsoft.com/dynimg/IC70642.gif" alt="" width="259" height="142" data-markzhi="registered" />

但是如果我们用overflow:hidden和zoom:1，分别触发BFC和hasLayout，那么，结果会是如何呢？

加上触发条件的代码如下
<pre class="prettyprint">&lt;div style="float:left; border: 2px solid red"&gt; 123&lt;/div&gt;
&lt;span style="border: 2px solid blue;display:block;overflow:hidden;*zoom:1"&gt;
     The quick brown fox jumped over the lazy dog's back.
     The quick brown fox jumped over the lazy dog's back. 
     The quick brown fox jumped over the lazy dog's back.
     The quick brown fox jumped over the lazy dog's back. 
     The quick brown fox jumped over the lazy dog's back.
&lt;/span&gt;​</pre>
结果如下图，<a href="http://jsfiddle.net/Rt2p7/6/" target="_blank">点此查看demo</a>

<img class="alignnone" title="文字不环绕" src="http://i.msdn.microsoft.com/dynimg/IC90668.gif" alt="" width="268" height="163" data-markzhi="registered" />

那么，实际开发中，这个特性可以用于解决什么问题呢？

比如百度知道（<a href="http://zhidao.baidu.com/">http://zhidao.baidu.com/</a>）首页右栏有一个本周知道之星

<img class="alignnone" title="asdas " src="http://pic.yupoo.com/maisui99/BPrg0dXD/kfQ4D.png" alt="" width="180" height="65" />

结构也很简单，就是
<pre class="prettyprint">&lt;img/&gt;
&lt;div&gt;
 &lt;h4&gt;天涯魔鬼训练营&lt;/h4&gt;
 &lt;p&gt;大将军 十八级&lt;/p&gt;
&lt;/div&gt;</pre>
他给img和div分别加了float:left来解决左右栏排版的问题。

但是，假设（仅仅是假设）描述部分多了几个字，就变成了这样

<img class="alignnone" title="1" src="http://pic.yupoo.com/maisui99/BPrhY50Y/HTxS1.png" alt="" width="234" height="138" data-markzhi="registered" />

实际情况中不应该存在那么高的等级，但是至少，我们有办法提供布局的容错性。

那么，如果我们将img设置float，div不设置float，效果就变成了这样：

<img class="alignnone" title="1" src="http://pic.yupoo.com/maisui99/BPrjogRc/xMg8J.png" alt="" width="204" height="113" />

我多加了几个字，显得有些夸张，很明显，结果依然不是我们想要的。

我们想要的结果应该是这样。

<img class="alignnone" title="1" src="http://pic.yupoo.com/maisui99/BPseI0CC/XjWxK.png" alt="" width="209" height="118" />

怎么样才能在文字长度不可控的情况下，保证布局的稳定性呢？

再回到之前讲的共同点1，你应该知道怎么解决这个问题了。

<a href="http://jsfiddle.net/Rt2p7/7/" target="_blank">点此查看demo</a>

当然，还有更多应用的场景

例如一个简单的三栏布局，左右两栏定宽，中间部分自适应，<a href="http://jsfiddle.net/Rt2p7/9/" target="_blank">点此查看demo</a>
<h2>2.清除元素内部浮动</h2>
<a href="http://jsfiddle.net/Rt2p7/4/" target="_blank">点此查看示例</a>

在示例中，我们可以看到outer元素在设置overflow:hidden和zoom:1之后，元素内部浮动对外部的影响被清除。也就是我们最常用的清除浮动在IE5.5/6/7上生效的原理。
<pre class="prettyprint">.k2-fix-float:after{
 content:"\0020";
 display:block;
 height:0;
 clear:both;
}
.k2-fix-float{
 *zoom:1;
}</pre>
<h2>3.嵌套元素边距折叠问题的解决</h2>
<a href="http://jsfiddle.net/Rt2p7/10/" target="_blank">点此查看demo</a>
<h2>不同点</h2>
<h2>1.hasLayout的元素被限制为一个矩形</h2>
触发haslayout的元素是可以设置宽高的，而触发BFC的元素不一定可以设置宽高，比如一个行内元素，设置float或者设置overflow都可以触发BFC，但是前者可以设置宽高，后者却不能，但是仔细考虑一下，给一个行内元素设置overflow:hidden还是一见比较扯蛋的事情。

<a href="http://jsfiddle.net/Rt2p7/8/" target="_blank">点此查看demo</a>
<h2>2.hasLayout的元素设置display:inline后与inline-block行为类似</h2>
该特性在IE6/7下解决inline-block问题时也有遇到
<pre class="prettyprint">.k2-inline-block{
 display:-moz-inline-stack;
 display:inline-block;
 *display:inline;
 *zoom:1;
 vertical-align:middle;
 position:relative;/* 解决因为父容器{display:inline;}问题导致Firefox中li里面的链接不可点的bug */
 _position:static;/* 解决因为IE6中因为上一行代码带来在{position:relative}容器中移位在bug */
}</pre>
这个状态下的元素和普通文字一样在水平方向连续排列，受vertical-align的影响，并且可以按照容器大小自适应调整。
<h2>更多补充</h2>
BFC和hasLayout在实际开发中还是要分为两个内容分别看待，特别是haslayout这个属性，按照现在的状况，它带来的困扰还是蛮大的。

hasLayout相关的问题列几个，更多可以看最后的参考文献：

1. <a href="http://www.f2es.com/haslayout-width-auto/" target="_blank">浮动元素的宽度自适应问题</a>

2.<a href="http://positioniseverything.net/explorer/ie-listbug.html " target="_blank">相对定位元素本身不会触发hasLayout，但是在刷新页面，调整窗口，滚动页面，选中内容的时候，会出现内容消失或者错误，因为IE在设置相对定位元素之后，如果需要做偏移处理等等，会忘了告诉其子孙元素进行“重绘”。</a>
<p style="text-align: left;">3.<a href="http://www.positioniseverything.net/abs_relbugs.html " target="_blank">绝对定位元素如果没有触发hasLayout带来的问题</a></p>
<p style="text-align: left;">4.<a href="http://msdn.microsoft.com/workshop/author/filter/filters.asp" target="_blank">滤镜是只适用于hasLayout的元素的</a></p>

<h2 style="text-align: left;">参考资料</h2>
本文所用到的CSS解决方案来自口碑网K2框架，详细可以访问<a href="https://github.com/f2e/k2">https://github.com/f2e/k2</a>，K2框架改进自YUI3，作为口碑网前端、前后端的解决方案。
<ul>
	<li><a href="http://yiminghe.iteye.com/blog/367384" target="_blank">on having layout</a></li>
	<li><a href="http://positioniseverything.net/explorer/threepxtest.html" target="_blank">The IE6 Three Pixel Text-Jog</a></li>
	<li><a href="http://www.yuiblog.com/blog/2010/05/19/css-101-block-formatting-contexts/" target="_blank">CSS 101: Block Formatting Contexts</a></li>
	<li><a href="http://thinkvitamin.com/design/everything-you-know-about-clearfix-is-wrong/" target="_blank">Everything you Know about Clearfix is Wrong</a></li>
	<li><a href="http://dev.l-c-n.com/IEW/simulations.php" target="_blank">Block formating contexts, ‘hasLayout’ – IE Window vs CSS2.1 browsers: simulations</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/library/bb250481%28VS.85%29.aspx" target="_blank">"HasLayout" Overview</a></li>
	<li><a href="http://www.w3.org/TR/CSS21/visuren.html#float-rules" target="_blank">Visual formatting model</a></li>
</ul> ]]></description>
            <pubDate>2012年03月20日</pubDate>
        </item>
                <item>
            <title>【译】在现阶段使用HTML5语义标签</title>
            <link>http://www.w3ctech.com/p/1087</link>
            <guid>http://www.w3ctech.com/p/1087</guid>
            <category>前端技术</category>
            <description><![CDATA[ <blockquote>原文地址：<a href="http://www.nczonline.net/blog/2011/03/22/using-html5-semantic-elements-today/">http://www.nczonline.net/blog/2011/03/22/using-html5-semantic-elements-today/</a></blockquote>
<h2>存在的问题</h2>
现阶段使用HTML5标签可能遇到的最大问题就是如何在不支持新标签的浏览器中做恰当的处理。当我们在页面中使用HTML5元素时，可能会得到三种不同的结果。

结果1：标签被当作错误处理并被忽略。那么DOM构建的时候，就会当作这个标签不存在。

结果2：标签会被当作错误处理，并在DOM构建的时候依然会按照预期的代码进行创建，并且HTML标签会被构造成行内元素（也就是说虽然不能识别，但是代码里section标签依然会在dom中创建一个对应section节点，但是属于行内元素）。

结果3：标签被识别为HTML5标签，然后用DOM节点对其进行替换。DOM在构建的时候和预想的一致，并且合适的样式会应用到标签上（大部分情况下是块级元素）。

有一个具体的例子，思考如下的代码：
<pre class="prettyprint" rel="HTML">&lt;div class="outer"&gt;
 &lt;section&gt;
 &lt;h1&gt;title&lt;/h1&gt;
 &lt;p&gt;text&lt;/p&gt;
 &lt;/section&gt;
&lt;/div&gt;</pre>
很多浏览器（比如Firefox 3.6和Safari4）解析的时候都会将div作为最外层的元素，然后div里面是一个识别不了的元素（section），它会在DOM中创建，并被作为一个行内元素存在。h1和p元素都是作为section元素的子节点。因为section在DOM中真实存在，所以也可以修改其样式。这种情况对应结果2。

IE9之前的版本会认为section标签是一个错误，并直接将其忽略，那么h1和p标签会被解析，然后成为div标签的子节点。&lt;/section&gt;也会被认为是一个错误并直接跳过。在这些浏览器中实际有效的代码是这样的：
<pre class="prettyprint" rel="HTML">&lt;div class="outer"&gt;
 &lt;h1&gt;title&lt;/h1&gt;
 &lt;p&gt;text&lt;/p&gt;
&lt;/div&gt;</pre>
那么，旧版本的IE浏览器除了生成的DOM结构和其他浏览器不一样，其对不可识别标签的容错能力还是很棒的。因为section节点没有在DOM树中构建，所以也就不能给其增加样式。这种情况对应结果1。

当然，支持HTML5的浏览器比如IE9，Firefox4+，Safari5+会创建正确的DOM结构，然后这些标签会默认附带HTML5规范中定义的默认样式。

那么，我们所面临的最大问题就是同样的代码在不同的浏览器中形成了不同的DOM结构，并且含有不同的样式。
<h2>解决方案</h2>
人们想出了很多在现阶段页面中使用HTML5元素的解决方案。每一个解决方案为了做到兼容都会遇到一些特定的问题。
<h2>JavaScript解决方案</h2>
JavaScript解决方案目的是解决在旧版本的IE中样式应用的问题。老版本的IE不会识别不明元素已经是一个耳熟能详的特性，而如果这些元素已经通过document.createElement()创建，那么浏览器就可以识别这些标签，并可以将其在DOM树中构建，然后允许开发者对其应用样式。

这个方法可以确保HTML5标签能在旧版本IE中对应创建DOM节点，然后可以对其应用样式。这个方法将HTML5块级元素设置成display:block，从而可以在各个浏览器中做到兼容。

我不喜欢这个解决方案，因为它破坏了我最主要的web应用开发原则：我们不应该使用JavaScript来控制布局。不仅仅是因为这个做法给那些禁用脚本的用户带来了糟糕的用户体验，更重要的是，如果我们希望我们的web应用代码是面向未来，并且维护性高的，那么必须将视图相关部分分离出来。这个方案对在跨浏览器中构建相同的DOM结构很有帮助，也可以确保你的JavaScript和CSS在各个地方运行结果相同，但是这个优势并不能改变我对这个方法的不认同。
<h2>Namespace hack</h2>
永远不要缺乏使用hack解决问题的能力，在IE中还有其他技术来让浏览器识别不明的标签。这个来自Elco Klingen日志的方法一开始引起了广泛的关注。该技术包含了一个XML形式的命名空间，并使用了含有namespace前缀的元素。例如：
<pre class="prettyprint" rel="HTML">&lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:html5="http://www.w3.org/html5/"&gt;
&lt;body&gt;
 &lt;html5:section&gt;
 &lt;!-- content --&gt;
 &lt;/html5:section&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
前缀html5是纯粹是用于这个例子而且也不是官方支持的，你甚至可以用"foo"作为前缀，结果还是一样。有了前缀之后，IE会识别新的元素，从而可以应用样式。在其他浏览器中一样有效，那么最后，你就成功地在各个浏览器中构建了一样的元素和一样的样式。

这个方法的缺陷很明显：你必须在HTML文档中使用XML格式的命名空间，同样，你也需要在css中这么做:
<pre class="prettyprint" rel="CSS">html5\:section {
 display: block;
}</pre>
这并不是我期望Web开发者编写代码的方式。这是一个非常杰出的解决方案，但是这让应用变得不自然。我不希望看到文件中充满了带命名空间的元素。
<h2>Bulletproof技术（防弹衣技术）</h2>
我在YUIConf2010上第一次接触到这个技术，当时是Tantek Çelik在做一个名为《HTML5: Right Here, Right Now》的分享。Tantek建议在所有新的HTML5块级元素中增加一个内部的div元素，然后包含一个CSS class，用这个元素来替代HTML元素（类似在里面穿了一件防弹衣），例如：
<pre class="prettyprint" rel="HTML">&lt;section&gt;
&lt;div class="section"&gt;
 &lt;!-- content --&gt;
&lt;/div&gt;&lt;/section&gt;</pre>
在应用样式的时候，Tantek推荐直接给div增加样式，而不是给新元素增加样式

推荐使用：
<pre class="prettyprint" rel="CSS">.section {
 color: blue;
}</pre>
而不是：
<pre class="prettyprint" rel="CSS">section {
 color: blue;
}</pre>
这个方案的原理是用简单的方式将原来的样式应用方式转移到一个代表了HTML5标签的元素上。由于我一般情况下不会将样式通过标签名的方式应用到元素上，所以我并不支持他的建议。

这个方案的缺陷是不同的浏览器构建了不同的DOM结构，那么你必须在编写JavaScript和CSS的时候格外小心。获取子节点或者父节点的时候，不同的浏览器返回的结果可能会不一样。特别是在下面的代码中：
<pre class="prettyprint" rel="HTML">&lt;div class="outer"&gt;
 &lt;section&gt;
&lt;div class="section main"&gt;
 &lt;!-- content --&gt;
 &lt;/div&gt;&lt;/section&gt;
&lt;/div&gt;</pre>
<h2>反向的bulletproof技术</h2>
还有一些文章，比如Thierry Koblentz写的《HTML elements and surrogate DIVs》，尝试使用和Tanteck方案相反的技术，也就是把HTML5元素放在div元素内部，例如：
<pre class="prettyprint" rel="HTML">&lt;div class="section"&gt;
&lt;section&gt;
 &lt;!-- content --&gt;
&lt;/section&gt;
&lt;div&gt;</pre>
这个方案唯一的不同是HTML5元素的位置，其他都一样。喜欢这个技术的支持者认为他的一致性很好（适用于所有的元素，包括&lt;hgroup&gt;）。但是DOM结构的不同让这个方案意义变得不大。他的主要优势是技术上的一致性。
<h2>我的方案</h2>
我的主要目标是确保我只需要修改HTML部分。这就意味着不需要修改CSS和JavaScript。为什么会有这样的需求？需要修改的Web应用视图越多，你越有可能制造bug。将改变限制到一个视图也就限制了bug的出现，即使出现了bug，也可以减少你查找错误的范围。如果一个视图破相了，我可以知道这是因为我增加了一个section元素，而不是考虑是不是CSS文件修改来带的影响。

在研究了所有这些解决方案，并进行一些尝试和设计之后，我回到了Tantek的方案。这是唯一一个只需要修改HTML而不用动CSS和HTML的方案。现在，我在他的方案基础上做了一些改进，来达到我想要的结果。

首先，我不会给那些代表HTML5元素的class增加样式（所以我不会使用.section这样的选择器）。我保留了div元素，然后再增加一个带语义的class来应用样式，并作为进行JavaScript操作的钩子。例如，这样的代码：
<pre class="prettyprint" rel="HTML">&lt;div class="content"&gt;
 &lt;!-- content --&gt;
&lt;/div&gt;</pre>
经过改进后：
<pre class="prettyprint" rel="HTML">&lt;section&gt;
&lt;div class="section content"&gt;
 &lt;!-- content --&gt;
&lt;/div&gt;
&lt;/section&gt;</pre>
这样的修改完成后，我依然使用.content作为样式和脚本的入口。这也意味着我不需要修改CSS和JavaScript。

然后，为了避免hgroup标签这样的情况，我选择不使用这个标签。我在我已有的所有页面中没有找到任何一个使用了这个标签的。由于hgroup标签只能包含标题元素，如果你确实想要使用这个标签，那么使用hrgoup来包含本身是非常安全的（假设它没有包含其他的块级元素）。

我花了很多时间来测试比较bulletproof和反向的bulletproof哪个更好一些。我做选择时最主要的决定因素就是反向的bulletproof需要我去增加CSS代码。在那些为HTML5标签创建了DOM节点但是没有应用默认样式的元素来说，div元素里包含了一个HTML5块级元素在很多情况下都会搅乱我的布局，因为创建的DOM节点是行内元素。我不得不明确增加CSS规则来让这个节点变成块级元素从而可以正常布局，这也就违反了我不修改CSS文件的初衷。
<h2>论证</h2>
在与这个知识点相关的讨论中，有一件事让我觉得很沮丧，人们怎么可以这么快就否定一个解决方案，仅仅因为发现这个方案至少在一种情况下不管用。我在这里展示的所有方案都不是完美的。他们也肯定没有覆盖所有你可能遇到的情况。在你给我展示任何一项技术的时候，我基本上可以保证找到一种情况，在这种情况下你所展示的技术是没有用处的。但是这样并不能让这个技术失去价值，它可以让你了解技术上的限制从而做出更好的选择。

在我的研究中，我使用了多个页面，然后在这些页面上使用修改过后的bulletproof技术。我分别在简单和复杂的布局中，含有和不含有JavaScript交互进行测试。在每一个例子中，我只需要修改HTML就可以让页面表现正确（不修改JavaScript和CSS）。那么，子节点和父节点的问题怎么办？有趣的事情是我在测试中并没有遇到这样的问题。

但是，理由很简单，因为我对代码苛刻的态度。我认真地做了第二遍检查：
<ul>
	<li>标签名和ID不会用于应用样式（只是用class）</li>
	<li>尽量选择常用的CSS选择器并且尽量减少选择器的使用</li>
	<li>JavaScript代码不依赖于特定的DOM结构</li>
	<li>标签名不用于操作DOM</li>
</ul>
我注意到另一个有趣的事情是我使用了HTML5元素作为容器。而这些新的元素仅仅是作为功能性模块的边界。你应该花费你的大部分时间为内部的元素编写样式和脚本而不是处理各个模块间的样式和脚本。由于我的JavaScript和CSS标签都应用在容器的内部，所以一切都显得很顺利。我想这才是一个真正的代码质量高的网站。
<h2>总结</h2>
我最后决定并推荐大家使用的是Tantek的bulletproof技术的改进版。很明显，在CSS和JavaScript领域里，这个名字显得有些不太恰当，但是在我的实验里，它确实允许我仅仅改变页面的HTML部分的同时还能保证页面正常工作。我确信关于这个主题的辩论仍然会持续在公司和网络上，而我希望的是这些文章能够帮助你做出明智的选择。 ]]></description>
            <pubDate>2012年03月15日</pubDate>
        </item>
                <item>
            <title>通过什么途径能够深入了解JavaScript引擎是如何工作的？</title>
            <link>http://www.w3ctech.com/p/1080</link>
            <guid>http://www.w3ctech.com/p/1080</guid>
            <category>JavaScript</category>
            <description><![CDATA[ <p>昨天收到一封来自深圳的一位前端童鞋的邮件，邮件内容如下（很抱歉，未经过他的允许，公开邮件内容，不过我相信其他人肯定也有同样的问题，所以，直接把问题原文抛出来）：</p>

<p>“读了你的几篇关于JS（变量对象、作用域、上下文、执行代码）的文章，我个人觉得有点抽象，难以深刻理解。我想请教下通过什么途径能够深入点的了解javascript解析引擎在执行代码前后是怎么工作的，ecma英文版实在看不下去呵呵。”</p>

<p>其实这个问题个人觉得太笼统了，直接回答很难回答，所以，我打算先把他的问题拆解成如下几个子问题，并对其表达个人的观点，希望对有同样困惑的童鞋能够有所帮助。</p>

<h2>1. 什么是JavaScript解析引擎？</h2>

<p>简单地说，JavaScript解析引擎就是能够“读懂”JavaScript代码，并准确地给出代码运行结果的一段程序。比方说，当你写了 <em>var a = 1 + 1;</em> 这样一段代码，JavaScript引擎做的事情就是看懂（解析）你这段代码，并且将a的值变为2。</p>

<p>学过编译原理的人都知道，对于静态语言来说（如Java、C++、C），处理上述这些事情的叫<strong>编译器（Compiler）</strong>，相应地对于JavaScript这样的动态语言则叫<strong>解释器（Interpreter）</strong>。这两者的区别用一句话来概括就是：<strong>编译器是将源代码编译为另外一种代码（比如机器码，或者字节码），而解释器是直接解析并将代码运行结果输出</strong>。 比方说，firebug的console就是一个JavaScript的解释器。</p>

<p>但是，现在很难去界定说，JavaScript引擎它到底算是个解释器还是个编译器，因为，比如像V8（Chrome的JS引擎），它其实为了提高JS的运行性能，在运行之前会先将JS编译为本地的机器码（native machine code），然后再去执行机器码（这样速度就快很多），相信大家对<strong>JIT（Just In Time Compilation）</strong>一定不陌生吧。</p>

<p>我个人认为，不需要过分去强调JavaScript解析引擎到底是什么，了解它究竟做了什么事情我个人认为就可以了。对于编译器或者解释器究竟是如何看懂代码的，翻出大学编译课的教材就可以了。</p>

<p>这里还要强调的就是，JavaScript引擎本身也是程序，代码编写而成。比如V8就是用C/C++写的。</p>

<h2>2. JavaScript解析引擎与ECMAScript是什么关系？</h2>

<p>JavaScript引擎是一段程序，我们写的JavaScript代码也是程序，如何让程序去读懂程序呢？这就需要定义规则。比如，之前提到的<em>var a = 1 + 1;</em>，它表示：</p>

<ul><li>左边var代表了这是申明（declaration）,它申明了a这个变量</li>
<li>右边的+表示要将1和1做加法</li>
<li>中间的等号表示了这是个赋值语句</li>
<li>最后的分号表示这句语句结束了</li>
</ul><p>上述这些就是规则，有了它就等于有了衡量的标准，JavaScript引擎就可以根据这个标准去解析JavaScript代码了。那么这里的ECMAScript就是定义了这些规则。其中ECMAScript 262这份文档，就是对JavaScript这门语言定义了一整套完整的标准。其中包括：</p>

<ul><li>var，if，else，break，continue等是JavaScript的关键词</li>
<li>abstract，int，long等是JavaScript保留词</li>
<li>怎么样算是数字、怎么样算是字符串等等</li>
<li>定义了操作符（+，-，&gt;，&lt;等）</li>
<li>定义了JavaScript的语法</li>
<li>定义了对表达式，语句等标准的处理算法，比如遇到<strong>==</strong>该如何处理</li>
<li>⋯⋯</li>
</ul><p><strong>标准</strong>的JavaScript引擎就会根据这套文档去实现，注意这里强调了<strong>标准</strong>，因为也有不按照标准来实现的，比如IE的JS引擎。这也是为什么JavaScript会有兼容性的问题。至于为什么IE的JS引擎不按照标准来实现，就要说到浏览器大战了，这里就不赘述了，自行Google之。</p>

<p>所以，简单的说，ECMAScript定义了语言的标准，JavaScript引擎根据它来实现，这就是两者的关系。</p>

<h2>3. JavaScript解析引擎与浏览器又是什么关系？</h2>

<p>简单地说，JavaScript引擎是浏览器的组成部分之一。因为浏览器还要做很多别的事情，比如解析页面、渲染页面、Cookie管理、历史记录等等。那么，既然是组成部分，因此一般情况下JavaScript引擎都是浏览器开发商自行开发的。比如：IE9的Chakra、Firefox的TraceMonkey、Chrome的V8等等。</p>

<p>从而也看出，不同浏览器都采用了不同的JavaScript引擎。因此，<strong>我们只能说要深入了解哪个JavaScript引擎</strong>。</p>

<h2>4. 深入了解其内部原理的途径有哪些？</h2>

<p>搞清楚了前面三个问题，那这个问题就好回答了。个人认为，主要途径有如下几种（依次由浅入深）：</p>

<ul><li>看讲JavaScript引擎工作原理的书<br />
这种方式最方便，不过我个人了解到的这样的书几乎没有，但是<a href="http://dmitrysoshnikov.com/" target="_blank">Dmitry A.Soshnikov</a>博客上的文章真的是非常的赞，建议直接看英文，实在英文看起来吃力的，可以看我翻译的<a href="http://blog.goddyzhao.me/JavaScript-Internal" target="_blank">译本</a></li>
<li>看ECMAScript的标准文档<br />
这种方式相对直接，原汁原味，因为引擎就是根据标准来实现的。目前来说，可以看<a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf" target="_blank">第五版</a>和<a href="http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf" target="_blank">第三版</a>，不过要看懂也是不容易的。</li>
<li>看JS引擎源代码<br />
这种方式最直接，当然也最难了。因为还牵涉到了如何实现词法分析器，语法分析器等等更加底层的东西了，而且并非所有的引擎代码都是开源的。</li>
</ul><h2>5. 以上几种方式中第一种都很难看明白怎么办？</h2>

<p>其实第一种方式中的文章，作者已经将文档中内容提炼出来，用通俗易懂的方式阐述出来了。如果，看起来还觉得吃力，那说明还缺少两块的东西：</p>

<ul><li>对JavaScript本身还理解的不够深入<br />
如果你刚刚接触JavaScript，或者说以前甚至都没有接触过。那一下子就想要去理解内部工作原理，的确是很吃力的。首先应该多看看书，多实践实践，从知识和实践的方式来了解JavaScript预言特性。这种情况下，你只需要了解现象。比方说，<em>(function(){})()</em> 这样可以直接调用该匿名函数、用闭包可以解决循环中的延迟操作的变量值获取问题等等。要了解这些，都是需要多汲取和实践的。实践这里就不多说了，而知识汲取方面可以多看看书和博客。这个层面的书就相对比较多了，<a href="http://www.amazon.com/Professional-JavaScript-Developers-Nicholas-Zakas/dp/1118026691/" target="_blank">《Professional JavaScript for Web Developers》</a>就是本很好的书（中文版请自行寻找）。</li>
<li>缺乏相应的领域知识<br />
当JavaScript也达到一定深度了，但是，还是看不大明白，或者没法很深入到内部去一探究竟。那就意味着缺少对应的领域知识。这里明显的就是编译原理相关的知识。不过，其实对这块了解个大概基本看起来就没问题了。要再继续深入，那需要对编译原理了解的很深入，比如说词法分析采用什么算法，一般怎么处理。会有什么问题，如何解决，AST生成算法一般有哪几种等等。那要看编译原理方面的书，也有基本经典的书，比如<a href="http://www.amazon.com/Compilers-Principles-Techniques-Tools-2nd/dp/0321486811/" target="_blank">《Compilers: Principles, Techniques, and Tools》</a>这本也是传说中的龙书，还有非常著名的<a href="http://mitpress.mit.edu/sicp/full-text/book/book.html" target="_blank">《SICP》</a>和<a href="http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/" target="_blank">《PLAI》</a>。不过其实根据个人经验，对于Dmitry的文章，要看懂它，只要你对JavaScript有一定深度的了解，同时你大学计算机的课程都能大致掌握了（尤其是操作系统），也就是说基础不错，理解起来应该没问题。因为这些文章基本没有涉及底层编译相关的，只是在解释文档的内容，并且其中很多东西都是相通的，比如：context的切换与CPU的进程切换、函数相关的的局部变量的栈存储、函数退出的操作等等都是一致的。</li>
</ul><p>以上就是个人对这个问题的看法，除此之外，我觉得，学习任何技术都不能操之过急，要把基础打扎实了，这样学什么都会很快。</p> ]]></description>
            <pubDate>2012年03月02日</pubDate>
        </item>
                <item>
            <title>CoffeeScript入门实践</title>
            <link>http://www.w3ctech.com/p/1065</link>
            <guid>http://www.w3ctech.com/p/1065</guid>
            <category>JavaScript</category>
            <description><![CDATA[ <embed src="http://player.youku.com/player.php/sid/XMzU4ODU5NDA0/v.swf" allowFullScreen="true" quality="high" width="480" height="400" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash"></embed>

<p>嗨，大家好。</p>
<p>在这一期的节目中，我们将介绍下CoffeeScript, 那么什么是CoffeeScript呢？CoffeeScript是一门小语言，也是一个编译器。用CoffeeScript编写的代码，可以编译成JavaScript代码。</p>
<p>CoffeeScript简化了JavaScript的编写，同时运用了JavaScript最佳实践模式。</p>
<h2>本期节目将分为3个部分</h2>
<ol>
<li>1. 第一部分中我们讲述安装的过程</li>
<li>2. 第二部分我们将看如何使用它</li>
<li>3. 第三部分中我们将看它如何简化了JavaScript的编写，同时怎么保证了最佳实践模式。</li>
</ol>
<h2>一、安装的过程</h2>
<p>要安装CoffeeScript，需要先安装node.js和npm。在mac 和 linux 的环境下，CoffeeScript的安装是相当容易的。比较复杂的呢是在Windows的环境下安装。所以我们着重讲一下在Windows环境下的安装方式。</p>
<p>首先我们先到node.js的网站下载在Windows版本的node.js。下载地址：http://nodejs.org/#download</p>
<p>下载后只要双击msi文件便可安装，整个过程是自动的。最近，npm也被加入到Node的Windows版本中，所以就不用额外再安装了。</p>
<p>安装完Node（包括npm）后，我们到Programm Files下，可以看到nodejs文件夹，在文件夹里，有node.exe, 为了方便，我在桌面上放了个快捷方式。</p>
<p>之后，我们到CoffeeScript的github页面下载CoffeeScript：https://github.com/jashkenas/coffee-script/downloads</p>
<p>下载并解压，我下载的到版本解压缩后的目录是jashkenas-coffee-script-127653b。我们可以把它放到另一个目录中，在这里我们把它放在C盘的dev目录中。</p>
<p>此时，Node和CoffeeScript在硬盘中的目录分别是：</p>
<p> Node：C:\Program Files\nodejs\</p>
<p> CoffeeScript：C:\dev\jashkenas-coffee-script-127653b</p>
<p>接下来，在桌面上建一个文件，命名为coffee.cmd。在任何一种编辑器下打开它。在里面打入下面的一段命令：</p>
<pre rel="cmd" class="prettyprint">
@echo off
node.exe C:\dev\jashkenas-coffee-script-127653b\bin\coffee %*
</pre>
<p>保存文件。之后把这个coffee.cmd 放到nodejs目录内。</p>

<h2>二、.使用</h2>

<p>在dev或任何其他目录中，建立一个目录，比如js。</p>
<p>在这个文档下，我们创建一个文件，命名为test.coffee。</p>
<p>这时打开cmd，打入下面的命令:
<pre rel="cmd" class="prettyprint">
&gt; cd C:\dev\js
&gt; coffee -w -c test.coffee

//-w 的全名是 --watch, 是实时编辑的命令
//-c 的全名是 --compile, 是编译的命令
</pre>
</p><p>这时，会看到js目录中生成了test.js。在编辑器中打开test.js，可以看到一个匿名函数。这时当我们在test.coffee中打入任何代码，保存后，可以看到test.js被同步更新。</p>
<p>除此之外，我们还可以看到很多其它的命令：</p>
<p>把src目录中的CoffeeScript文件目录树的js在lib目录中编译成平行树
<pre rel="CoffeeScript" class="prettyprint">
coffee --compile --output lib/ src/
</pre>
</p><p>把多个文件串连成一个文件</p>
<pre rel="CoffeeScript" class="prettyprint">
coffee --join project.js --compile src/*.coffee
</pre>

<h2>三、使用实例</h2>

<h3>(一) 函数</h3>
<p>如果我们输入下面的代码：</p>
<pre rel="CoffeeScript" class="prettyprint">
square = (x) -&gt; x * x
</pre>
<p>在保存后，看生成的文件，我们可以看到文件的最上方有 square 变量的声明，下面我们把一个匿名函数分配给了这个变量：</p>
<pre rel="JavaScript" class="prettyprint">
var square;
square = function(x) {
    return x * x;
};
</pre>

<p>当我们再输入下面的代码时:</p>
<pre rel="CoffeeScript" class="prettyprint">
cube = (x) -&gt; square(x) * x
</pre>
<p>会显示为：</p>
<pre rel="JavaScript" class="prettyprint">
var cube, square;
square = function(x) {
    return x * x;
};

cube = function(x) {
    return square(x) * x;
};
</pre>

<p>函数也可能有参数的默认值。用一个非空的参数覆盖默认值。</p>
<pre rel="CoffeeScript" class="prettyprint">
fill = (container, liquid = "coffee") -&gt;
"Filling the #{container} with #{liquid}..."
</pre>
<p>会变为：</p>
<pre rel="JavaScript" class="prettyprint">
var fill;
fill = function(container, liquid) {
if (liquid == null) liquid = "coffee";
return "Filling the " + container + " with " + liquid + "...";
};
</pre>

<h3>(二) 对象</h3>
<p>下面的CoffeeScript:</p>
<pre rel="CoffeeScript" class="prettyprint">
kids =
brother:
name: "Max"
age: 11
sister:
name: "Ida"
age: 9
</pre>

<p>会显示为：</p>
<pre rel="JavaScript" class="prettyprint">
kids = {
    brother: {
        name: "Max",
        age: 11
    },
    sister: {
        name: "Ida",
        age: 9
    }
};
</pre>
<p>在JavaScript中，你不能使用保留字(???reserved words)。比如在没有用字符串引用它们的情况下，把class作为对象的属性。</p>
<p>CoffeeScript注意到用作键的对象和他们的报价为您的保留字，所以你不必担心它（例如，当使用jQuery）。下面这段：</p>
<pre rel="CoffeeScript" class="prettyprint">
$('.account').attr class: 'active'
log object.class
</pre>
<p>会显示为：</p>
<pre rel="JavaScript" class="prettyprint">
$('.account').attr({
"class": 'active'
});
log(object["class"]);
</pre>

<h3>（三） 词法作用域和变量安全</h3>

<p>这种行为实际上是相同于Ruby的局部变量作用域。</p>
<p>outer是不能重新声明在内部函数，因为它是已经在作用域内;</p>
<p>另一方面，inner在函数内部，不应该能够改变同名的外部变量的值，因此有自身的声明。</p>
<p>所以下面一段：</p>
<pre rel="CoffeeScript" class="prettyprint">
outer = 1
changeNumbers = -&gt;
inner = -1
outer = 10
inner = changeNumbers()
</pre>
<p>会变成：</p>
<pre rel="JavaScript" class="prettyprint">
var changeNumbers, inner, outer;
outer = 1;
changeNumbers = function() {
    var inner;
    inner = -1;
    return outer = 10;
};
inner = changeNumbers();
</pre> ]]></description>
            <pubDate>2012年03月01日</pubDate>
        </item>
                <item>
            <title>【译】在本地存储中保存图片和文件</title>
            <link>http://www.w3ctech.com/p/1061</link>
            <guid>http://www.w3ctech.com/p/1061</guid>
            <category>JavaScript</category>
            <description><![CDATA[ <blockquote>原文地址：<a href="http://hacks.mozilla.org/2012/02/saving-images-and-files-in-localstorage/">http://hacks.mozilla.org/2012/02/saving-images-and-files-in-localstorage/</a></blockquote>
你可能已经对本地存储有所了解，本地存储在浏览器中快速存储数据的时候特别强大，并且已经在浏览器中存在多时。但是如何才能在本地存储中保存文件呢？

首先，推荐你先阅读<em><a href="http://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/">Storing images and files in IndexedDB</a>。</em>
<h2>使用JSON实现强大的本地存储控制</h2>
首先，我们先了解一些基本的本地存储相关的知识。你可以使用键值对的方式往本地存储中存储数据，就像这样：
<pre class="prettyprint">localStorage.setItem("name", "Robert");</pre>
而从本地存储中读取数据的方式如下：
<pre class="prettyprint">localStorage.getItem("name");</pre>
这样的存取方式非常不错，而且最多可以存储5M的数据，给你更多选择的空间。但是由于本地存储是基于字符串的存储，存储一串没有结构的字符串并不是一个理想的选择。因此，我们可以利用浏览器中原生的JSON支持来将JavaScript对象转化成字符串，从而保存到本地数据中，在读取的时候也可以将其转换回JavaScript对象。
<h2>图片的存储</h2>
我们的想法是做到将已经当前页面中已缓存的图片保存到本地存储中。不过就像我们之前已经确定的，本地存储只支持字符串的存取，那么我们要做的就是将图片转换成<a href="http://en.wikipedia.org/wiki/Data_URI_scheme" target="_blank">Data URI</a>。其中一种实现方式就是用canvas元素来加载图片。然后你可以以Data URI的形式从canvas中读取出当前展示的内容。

让我们看一个例子。
<pre class="prettyprint">//当图片加载完成的时候触发回调函数
elephant.addEventListener("load", function () {
 var imgCanvas = document.createElement("canvas"),
 imgContext = imgCanvas.getContext("2d");
 
 // 确保canvas元素的大小和图片尺寸一致
 imgCanvas.width = elephant.width;
 imgCanvas.height = elephant.height;
 
 // 渲染图片到canvas中
 imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
 
 // 用data url的形式取出
 var imgAsDataURL = imgCanvas.toDataURL("image/png");
 
 // 保存到本地存储中
 try {
 localStorage.setItem("elephant", imgAsDataURL);
 }
 catch (e) {
 console.log("Storage failed: " + e);
 }
}, false);</pre>
如果我们想要考虑地更长远一些，那么还可以利用JavaScript对象并做一些数据检查。在这个例子中，第一次我们从服务端读取图片，之后每一次页面加载时，我们就可以直接从本地存储中读取已读取过的图片。
<h2>HTML部分</h2>
<pre class="prettyprint">&lt;figure&gt;
 &lt;img id="elephant" src="about:blank" alt="A close up of an elephant"&gt;
 &lt;noscript&gt;
 &lt;img src="elephant.png" alt="A close up of an elephant"&gt;
 &lt;/noscript&gt; 
 &lt;figcaption&gt;A mighty big elephant, and mighty close too!&lt;/figcaption&gt;
&lt;/figure&gt;</pre>
<h2>JavaScript部分</h2>
<pre class="prettyprint">//在本地存储中保存图片
var storageFiles = JSON.parse(localStorage.getItem("storageFiles")) || {},
 elephant = document.getElementById("elephant"),
 storageFilesDate = storageFiles.date,
 date = new Date(),
 todaysDate = (date.getMonth() + 1).toString() + date.getDate().toString();
// 检查数据，如果不存在或者数据过期，则创建一个本地存储
if (typeof storageFilesDate === "undefined" || storageFilesDate &lt; todaysDate) {
 // 图片加载完成后执行
 elephant.addEventListener("load", function () {
 var imgCanvas = document.createElement("canvas"),
 imgContext = imgCanvas.getContext("2d");
// 确保canvas尺寸和图片一致
 imgCanvas.width = elephant.width;
 imgCanvas.height = elephant.height;
// 在canvas中绘制图片
 imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
// 将图片保存为Data URI
 storageFiles.elephant = imgCanvas.toDataURL("image/png");

 storageFiles.date = todaysDate;
// 将JSON保存到本地存储中
 try {
 localStorage.setItem("storageFiles", JSON.stringify(storageFiles));
 }
 catch (e) {
 console.log("Storage failed: " + e);
 }
 }, false);
// 设置图片
 elephant.setAttribute("src", "elephant.png");
}
else {
 // Use image from localStorage
 elephant.setAttribute("src", storageFiles.elephant);
}</pre>
注意：此处需要注意本地存储的容量，最好使用try...catch来控制异常。
<h2>保存任意格式的文件</h2>
使用canvas将图片转换成Data URI并保存到本地存储中的方式非常好，但是如果我们希望能找到一个可以保存任意格式文件的方式。

那么，这个过程就显的比较有趣了，我们需要用到：
<ul>
	<li><a href="https://developer.mozilla.org/en/XMLHttpRequest" target="_blank">XMLHttpRequest Level 2</a></li>
	<li><a href="https://developer.mozilla.org/en/DOM/BlobBuilder">BlobBuilder</a>（提供接口来构建Blob对象，Blob对象是BLOB (binary large object)，二进制大对象，是一个可以存储二进制文件的容器。在计算机中，BLOB常常是数据库中用来存储二进制文件的字段类型。BLOB是一个大文件，典型的BLOB是一张图片或一个声音文件，由于它们的尺寸，必须使用特殊的方式来处理（例如：上传、下载或者存放到一个数据库）。）</li>
	<li><a href="https://developer.mozilla.org/en/DOM/FileReader">FileReader</a></li>
</ul>
基本方法是：
<ol>
	<li>用XMLHttpRequest请求文件，然后将响应头设置为"arraybuffer"。</li>
	<li>将返回数据存放到BlobBuilder中</li>
	<li>获取blob，也就是文件内容</li>
	<li>使用FileReader对象读取文件并加载到文件中，最后保存到本地存储。</li>
</ol>
<pre class="prettyprint">// 获取文件
var rhinoStorage = localStorage.getItem("rhino"),
 rhino = document.getElementById("rhino");
if (rhinoStorage) {
 //如果已经存在则直接重用已保存的数据
 rhino.setAttribute("src", rhinoStorage);
}
else {
 // 创建XHR, BlobBuilder 和FileReader 对象
 var xhr = new XMLHttpRequest(),
 blobBuilder = new (window.BlobBuilder || window.MozBlobBuilder || window.WebKitBlobBuilder || window.OBlobBuilder || window.msBlobBuilder),
 blob,
 fileReader = new FileReader();
 xhr.open("GET", "rhino.png", true);
 //将响应头类型设置为“arraybuffer”，也可以使用"blob"，这样就不需要使用BlobBuilder来构建数据，但是"blob"的支持程度有限。
 xhr.responseType = "arraybuffer";
 xhr.addEventListener("load", function () {
 if (xhr.status === 200) {
 // 将响应数据放入blobBuilder中
 blobBuilder.append(xhr.response);
 // 用文件类型创建blob对象
 blob = blobBuilder.getBlob("image/png");
 // 由于Chrome不支持用addEventListener监听FileReader对象的事件，所以需要用onload
 fileReader.onload = function (evt) {
 // 用Data URI的格式读取文件内容
 var result = evt.target.result;
 // 将图片的src指向Data URI
 rhino.setAttribute("src", result);
 //保存到本地存储中
 try {
 localStorage.setItem("rhino", result);
 }
 catch (e) {
 console.log("Storage failed: " + e);
 }
 };
 // 以Data URI的形式加载blob
 fileReader.readAsDataURL(blob);
 }
 }, false);
 // 发送异步请求
 xhr.send();
}</pre>
<h2>使用“blob”作为响应头类型</h2>
在上面的例子中，我们使用的是“arraybuffer”作为响应头类型，然后使用BlobBuilder来创建可以由FileReader读取的数据。然而，"blob"作为响应头类型后，会直接返回一个blob对象，从而可以直接由FileReader读取。上面的例子可以改成这样：
<pre class="prettyprint">// Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
var rhinoStorage = localStorage.getItem("rhino"),
 rhino = document.getElementById("rhino");
if (rhinoStorage) {
 // Reuse existing Data URL from localStorage
 rhino.setAttribute("src", rhinoStorage);
}
else {
 // Create XHR, BlobBuilder and FileReader objects
 var xhr = new XMLHttpRequest(),
 fileReader = new FileReader();
 xhr.open("GET", "rhino.png", true);
 // Set the responseType to arraybuffer. "blob" is an option too, rendering BlobBuilder unnecessary, but the support for "blob" is not widespread enough yet
 xhr.responseType = "blob";
 xhr.addEventListener("load", function () {
 if (xhr.status === 200) {
 // onload needed since Google Chrome doesn't support addEventListener for FileReader
 fileReader.onload = function (evt) {
 // Read out file contents as a Data URL
 var result = evt.target.result;
 // Set image src to Data URL
 rhino.setAttribute("src", result);
 // Store Data URL in localStorage
 try {
 localStorage.setItem("rhino", result);
 }
 catch (e) {
 console.log("Storage failed: " + e);
 }
 };
 // Load blob as Data URL
 fileReader.readAsDataURL(xhr.response);
 }
 }, false);
 // Send XHR
 xhr.send();
}</pre>
<h2>浏览器支持情况</h2>
<ul>
	<li>本地存储——大部分主流浏览器都支持（在国外=。=）, including IE8.</li>
	<li>原生的JSON支持——支持情况和本地存储类似</li>
	<li>canvas元素——大部分主流浏览器都支持，从IE9开始</li>
	<li>XMLHttpRequest Level 2—— Firefox，Google Chrome， Safari 5+ 并计划在IE10和Opera 12中实现</li>
	<li>BlobBuilder——Firefox ，Google Chrome，并计划在IE10中实现. Safari和Opera情况不明.</li>
	<li>FileReader——Firefox ，Google Chrome，Opera 11.1之后的版本， 计划在IE10中实现. Safari情况不明.</li>
	<li>responseType “blob”——只在Firefox中支持. Google Chrome即将支持，IE10计划支持.  Safari和Opera情况不明。</li>
</ul> ]]></description>
            <pubDate>2012年02月26日</pubDate>
        </item>
                <item>
            <title>JavaScript 模式与反模式 - 第一集 （视频）</title>
            <link>http://www.w3ctech.com/p/1047</link>
            <guid>http://www.w3ctech.com/p/1047</guid>
            <category>前端技术</category>
            <description><![CDATA[ 这期的视频是根据我之前在github上的<a href="http://shichuan.github.com/javascript-patterns/" target="_blank">《JavaScript模式与反模式集合》</a>而做的视频专题。 源代码可到github（<a href="https://github.com/shichuan/javascript-patterns" target="_blank">https://github.com/shichuan/javascript-patterns</a>）上查看 ：）

<embed src="http://player.youku.com/player.php/sid/XMzU2MTU1NTg0/v.swf" allowFullScreen="true" quality="high" width="480" height="400" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash"></embed> ]]></description>
            <pubDate>2012年02月24日</pubDate>
        </item>
                <item>
            <title>【译】CSS media queries在JavaScript中的应用(二)</title>
            <link>http://www.w3ctech.com/p/982</link>
            <guid>http://www.w3ctech.com/p/982</guid>
            <category>JavaScript</category>
            <description><![CDATA[ <blockquote>原文链接：<a href="http://www.nczonline.net/blog/2012/01/19/css-media-queries-in-javascript-part-2/">http://www.nczonline.net/blog/2012/01/19/css-media-queries-in-javascript-part-2/</a></blockquote>
在我的前一篇文章中，我介绍了CSS media query在JavaScript中的应用，包括一个自制的实现函数和CSSOM Views里的matchMedia()方法。在CSS和JavaScript中，Media query都是那么实用，以至于我继续对其进行了一些研究，探索更好的利用方式。最后我发现，matchMedia()方法还有一些我在写第一篇文章时没有意识到的有趣特性。
<h2>matchMedia()和它的有趣特性</h2>
再次调用matchMedia()会返回一个MediaQueryList对象，这个对象可以让你确定给出的media类型是否和浏览器当前状态匹配。MediaQuery对象的matches属性会使用一个布尔型数据来表明匹配的结果。很明显，在每一次调用marches属性的时候，它都会获取一次浏览器的状态：
<pre rel="JavaScript" class="prettyprint">var mql = window.matchMedia("screen and (max-width:600px)");
console.log(mql.matches);
//resize the browser
console.log(mql.matches); //requeries</pre>
这显然非常实用，因为这样你就可以保持对MediaQueryList对象的引用，从而可以重复检查query与页面之间的状态。

Chrome和safari还有一个怪异的行为。即使matches属性的初始值是正确的，默认情况下还是不会更新matches的值，除非页面含有一个对应相同的query和至少一个规则定义的media块。比如说，为了让一个表现形式为”“screen and (max-width:600px)““的MediaQueryList对象正确显示出来（包括能正确触发事件），你必须在你的CSS中包含一些内容：
<pre rel="JavaScript" class="prettyprint">@media screen and (max-width:600px) {
 .foo { }
}</pre>
media块中必须含有至少一个CSS规则，但是该规则是可以为空的。只要这个规则存在于页面上，那么MediaQueryList对象就可以正确更新，并且所有通过addListener()绑定的事件都可以正确触发。

你可以使用JavaScript来修复这个问题：
<pre rel="JavaScript" class="prettyprint">var style = document.createElement("style");
style.appendChild(document.createTextNode("@media screen and (max-width:600px) { .foo {} }"));
document.head.appendChild(style); //WebKit支持document.head</pre>
当然你或许会需要为每一个使用matchMedia()访问的media query应用这个修复，这可能会显得有些繁杂。

Firefox中的实现也有一些怪异的特性。理论上，你可以注册一个处理器监听query状态的改变，这样你就不需要一直保持对MediaQUeryList对象的引用了，如下：
<pre rel="JavaScript" class="prettyprint">//在Firefox中无效
window.matchMedia("screen and (max-width:600px)").addListener(function(mql) {
 console.log("Changed!");
});</pre>
在Firefox中，即使media query是有效的，监听器或许仍然不会被调用。在我的测试中，它可能会被触发0到3次，然后再也不会被触发。Firefox团队已经了解了这个bug，并且应该很快会修复这个问题。所以，在使用这个方案的同时，你还是需要继续引用MediaQueryList对象来确保监听器被触发了：
<pre rel="JavaScript" class="prettyprint">//fix for Firefox
var mql = window.matchMedia("screen and (max-width:600px)");
mql.addListener(function(mql) {
 console.log("Changed!");
});</pre>
因为mql的存在，监听器就一直可以被触发。
<h2>监听器相关的更多内</h2>
在我的上一篇文章中，由于对一部分内容的误解，我对media query的描述有一些错误。监听器会在两个情景下被触发：
<ol>
	<li>media query一开始是有效的。就像前一个例子中，屏幕宽度变成600px或者更低。</li>
	<li>media query一开始是无效的。例如屏幕宽度大于600px。</li>
</ol>
这就是为什么需要将MediaQueryList对象传入到监听器中，这样你可以通过检查matches属性来确定media query是否有效。例如：
<pre rel="JavaScript" class="prettyprint">mql.addListener(function(mql) {
 if (mql.matches) {
 console.log("Matches now!");
 } else {
 console.log("Doesn't match now!");
 }
});</pre>
通过这样的代码，你就可以监控一个web应用的状态，从而可以做一些适当的调整。
<h2>是否需要对matchMedia()进行模拟（不支持的浏览器中）</h2>
在我在了解matchMedia()的时候，我试图创建一个函数模拟matchMedia()（原文称为polyfill，作为一种不支持matchMedia()方法情况下的替代措施）。Paul Irish使用类似我最近一篇文章里描述的技术实现了一个polyfill。Paul Hayes之后开设了一个分支来创建polyfill，使用了一个基于简单CSS transition的监听器来检测改变。然而，由于它依赖于CSS transitions，监听器的兼容性受到CSS transition兼容性的限制。加上调用matches不能再次获取浏览器状态与Firefox和webkit中的bug，让我坚信创建一个polyfill并不是一个正确的方向。毕竟，当真实环境中存在那么多明显的bug时，polyfill又怎么能正确执行。

我选择的方式是创建一个容器来包裹API的行为，从容器处消除这些问题。当然，我选择将这个API作为YUI Gallery的一个模块实现，叫做gallery-media。这个API很简单，并由两个方法组成。第一个是Y.Media.matches()，调用media query字符串并返回匹配结果。不需要记录任何对象，只需要直接这样获取：
<pre rel="JavaScript" class="prettyprint">var matches = Y.Media.matches("screen and (max-width:600px)");</pre>
第二个方法是Y.Media.on()，它允许你来指定一个media query和一个监听器，当media query生效或者失效时执行。监听器的参数是一个含有matches和media属性的对象，提供media query的信息。例如：
<pre rel="JavaScript" class="prettyprint">var handle = Y.Media.on("screen and (max-width:600px)", function(mq) {
 console.log(mq.media + ":" + mq.matches);
});
//detach later
handle.detach();</pre>
取代使用CSS transitions来监控改变，我使用了一个简单的onresize事件处理器。在桌面系统中，浏览器的尺寸是最有可能被改变的（在移动设备中，方向也有可能被该改变），那么我为旧的浏览器做了这么一个假设。API使用了原生的matchMedia()函数，在WebKit和Chrome中都有效并进行了一些修复，从而可以得到稳定的行为。
<h2>总结</h2>
JavaScript中的CSS media query比我想象的复杂一些，但是非常实用。我不觉得通过polyfill的方式修复marchMedia()是一个好主意，它让你不能在多个浏览器中使用相同的方式编码。好处是，它将你从bug和改变中隔离出来，从而看起来会更加先进一些。现在让我们使用JavaScript和CSS media query创造更多的可能。
<h2>参考</h2>
<ol>
	<li><a href="http://www.nczonline.net/blog/2012/01/03/css-media-queries-in-javascript-part-1/" target="_blank">CSS media queries in JavaScript, Part 1</a></li>
	<li><a href="https://twitter.com/#!/robflaherty/status/156581804046946304" target="_blank">Rob Flaherty’s tweet</a></li>
	<li><a href="https://bugs.webkit.org/show_bug.cgi?id=75903" target="_blank">matchMedia() MediaQueryList not updating</a></li>
	<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=716751" target="_blank">matchMedia() listeners lost</a></li>
	<li><a href="https://github.com/paulirish/matchMedia.js" target="_blank">matchMedia polyfill</a></li>
	<li><a href="https://github.com/fofr/matchMedia.js" target="_blank">matchMedia polyfill</a></li>
	<li><a href="https://github.com/nzakas/yui3-gallery/tree/master/src/gallery-media" target="_blank">YUI 3 Gallery Media module</a></li>
</ol>
前一篇：<a href="http://w3ctech.com/p/948" target="_blank">【译】CSS media queries在JavaScript中的应用(一)</a> ]]></description>
            <pubDate>2012年02月13日</pubDate>
        </item>
                <item>
            <title>【译】CSS media queries在JavaScript中的应用(一)</title>
            <link>http://www.w3ctech.com/p/948</link>
            <guid>http://www.w3ctech.com/p/948</guid>
            <category>前端技术</category>
            <description><![CDATA[ <blockquote>原文地址：<a href="http://www.nczonline.net/blog/2012/01/03/css-media-queries-in-javascript-part-1/">http://www.nczonline.net/blog/2012/01/03/css-media-queries-in-javascript-part-1/</a></blockquote>
在2011年初，我参与了一个关于JavaScript特性检测的项目。一些问题的出现让我觉得使用CSS media query或许会更好，所以我花了一些时间编写一个使用JavaScript操作CSS media queries的函数。我的思路很简单：如果我只需要基于media query就可以控制特定的CSS，那么，我也可以基于media query执行特定的JavaScript。
<pre rel="JavaScript" class="prettyprint">var isMedia = (function(){
 var div;
 return function(query){
 //如果&lt;div&gt;不存在, 则创建一个并让其隐藏
 if (!div){
 div = document.createElement("div");
 div.id = "ncz1";
 div.style.cssText = "position:absolute;top:-1000px";
 document.body.insertBefore(div, document.body.firstChild);
 }
 div.innerHTML = "_&lt;style media=\"" + query + "\"&gt; #ncz1 { width: 1px; }&lt;/style&gt;";
 div.removeChild(div.firstChild);
 return div.offsetWidth == 1;
 };
})();</pre>
这个函数的思路很简单。我创建了一个&lt;style&gt;节点，在里面设置了media属性来对应我正在测试的样式。这个样式会应用在&lt;div&gt;标签上，我需要做的就是检查这个样式是否已经应用到对应的节点。我觉得应该避免一些浏览器探测，所以我没有使用currentStyle或者getComputedStyle()，而是选择改变一个元素的宽度，然后用offsetWidth来检查这个改变。

很快，我们就创建了一个函数，并且它可以在几乎所有的浏览器中运行。和你猜的一样，在IE6和IE7上会有一些问题。在这两个个浏览器上，&lt;style&gt;元素是一个<a href="http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx" target="_blank">NoScope元素</a>（比如文本节点，注释节点或者script）。NoScope意味着当页面受到innerHTML或者其他类似的操作注入时，会发生一些可怕的事情。如果NoScope元素是作为HTML字符串的最前面部分被添加的，那么所有这些元素都会被丢弃。为了能正常使用NoScope元素，你必须确定这个元素不是HTML字符串的第一部分。因此，我在&lt;style&gt;元素签名增加了一条下划线，然后再将其删除，这样就能保证在IE6和IE7下保持正常。其他浏览地没有这个NoScope问题，但是使用这个技术并不是一个完美的方案（我之前说过我尽量要避免浏览器探测）。

最后，你可以这样使用这个函数：
<pre rel="JavaScript" class="prettyprint">if (isMedia("screen and (max-width:800px)"){
 //在screen模式下这样使用
}
if (isMedia("all and (orientation:portrait)")){
 //portrait模式下
}</pre>
isMedia()函数在所有浏览器里都工作地很好，它可以很好地检测media query在浏览器中的有效性。也就是说传入一个无效的media query会返回一个false。比如在IE6下，传入"screen"会返回true，但是更复杂的参数传入的话会返回false。这个结果是可以接收的，因为其他没有匹配到的media query中的任意CSS样式都不应该在对应的浏览器中应用。
<h2>CSSOM View</h2>
CSS Object Model（CSSOM）Views规范增加了对JavaScript操作CSS media query的原生支持，它在window对象下增加了matchMedia()方法。你可以传入一个CSS media query然后返回一个MediaQueryList对象。这个对象包括两个属性：matches，布尔值数据，表示CSS media query是否与当前的显示状态匹配；media对应传入的参数字符串。例如：
<pre rel="JavaScript" class="prettyprint">var match = window.matchMedia("screen and (max-width:800px)");
console.log(match.media); //"screen and (max-width:800px)"
console.log(match.matches); //true or false</pre>
到这里，API没有提供的支持和我之前的想法差不多。你或许会考虑为什么matchMedia()会返回一个对象？毕竟，如果没有匹配成功，返回的对象也毫无用处。答案就在addListener()和removeListener()上。

这两个方法允许你基于CSS media query与视图状态进行交互。例如，当模式转换到“portrait”模式时，或许你会想要有一个提示。你可以这么做：
<pre rel="JavaScript" class="prettyprint">var match = window.matchMedia("(orientation:portrait)");
match.addListener(function(match){
 if (match.media == "(orientation:portrait)") {
 //do something
 }
});</pre>
这段代码对media query进行了监听。当query值和当前的视图状态对应时，监听器对应的函数就会执行，而对应的MediaQueryList对象也会传入。用这个方式吗，你可以让你的JavaScript可以很快地响应布局变化，并且不需要用轮询的方式。那么，这里就和我的想法不太一样了，这个API允许你监听视图状态的改变，并响应调整界面的行为。

matchMeida()方法在Chrome，Safari5.1+，FireFox 9+和IOS 5+上的Safari上都已生效。这些是我了解并已核实的浏览器。IE和Opera依然没有在最近的几个版本中实现这个方法。

注意：WebKit上的实现有一个BUG，当MediaQueryList对象创建后，matches不会更新，query监听器也不会触发。希望这个问题能早点修复。
<h2>总结</h2>
CSS media query带来了一个在CSS和JavaScript中都适用的特性检测语法。我期望media query可以在未来成为JavaScript代码中的重要部分，在界面变化发生时，开发者能检测得到。实在没有理由说web应用的行为不应该响应布局的变化，而CSS media让我们变得更加强大。
<h2>参考</h2>
<a href="https://gist.github.com/08602e7d2ee448be834c" target="_blank">A function for detecting if the browser is in a given media mode</a>
<a href="http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx" target="_blank">MSDN: innerHTML Property</a>
<a href="http://www.w3.org/TR/cssom-view/">CSS Object Model View</a>
<a href="https://bugs.webkit.org/show_bug.cgi?id=75903">matchMedia() MediaQueryList is not updating</a> ]]></description>
            <pubDate>2012年02月10日</pubDate>
        </item>
                <item>
            <title>解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn</title>
            <link>http://www.w3ctech.com/p/935</link>
            <guid>http://www.w3ctech.com/p/935</guid>
            <category>前端技术</category>
            <description><![CDATA[ <a href="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png"><img class="alignnone size-full wp-image-819" title="decoding-jquery" src="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png" alt="" width="272" height="133" /></a>
<a href="http://www.weibo.com/shichuan86">石川</a>著, <a href="http://www.weibo.com/lisf">李松峰</a>编译

“OOP与jQuery”是“解码jQuery”系列中的一个子系列，主要讨论 jQuery 的内部构成及相关的OOP（Object Oriented Programming，面向对象编程）概念。

在这篇文章中，我们会讨论函数作用域、jQuery连缀模式和jQuery.fn。

<strong>1.函数作用域</strong>

我们都看到了，jQuery对象被包装在了很多层函数中。为什么我们用函数来定义作用域呢？因为JavaScript不能用花括号定义作用域。JavaScript变量只有全局作用域和函数作用域。

举例来说吧，为了把下面这个jQuery变量变成私有变量，必须把它包装在一个函数中：
<pre rel="JavaScript" class="prettyprint">function a() {
  var jQuery = "hellow world";
}
console.log(jQuery); // undefined</pre>
JavaScript函数具有词法作用域。什么意思呢？就是说，函数的作用域是在定义的时候创建的，而不是在执行的时候创建的。
<pre rel="JavaScript" class="prettyprint">var jQuery = 'hi there';
var f = function() {
  console.log(jQuery); // "undefined"
  var jQuery = "hello world";
};
f();
// undefined</pre>
所以，如果运行上面的代码，返回的值会是`undefined`，而不是`’hi there’`。 就是说，在同一个变量作用域或者同一个函数内，只要有使用var声明变量jQuery的语句，就可以在函数中的任何位置访问它，包括在var语句之前。所以上面的等同于：
<pre rel="JavaScript" class="prettyprint">var jQuery = 'hi there';
var f = function() {
  var jQuery; // same as -&gt; var jQuery = undefined;
  console.log(jQuery); // "undefined"
  jQuery = "hello world";
};
f();
// undefined</pre>
就是说，函数f有自己的作用域，它没有读var jQuery = 'hi there'。但在函数f内部，确实定义了jQuery变量，只不过调用console.log()时，jQuery还没有定义。

<strong>2.jQuery连缀模式</strong>

看看init方法，不知道你是否注意到了，这个方法返回this。
<pre rel="JavaScript" class="prettyprint">var jQuery = function( selector, context ) {
  // jQuery对象实际上就是一个“增强版的”init构造函数
  return new jQuery.fn.init( selector, context, rootjQuery );
}
jQuery.fn = jQuery.prototype = {
  init: function( selector, context, rootjQuery ) {
    //...
    return this;
    //...
  }
}</pre>
在jQuery中，可以在一个方法调用后面再连缀另一个方法调用。之所以能够如此，是因为每个方法都像这里一样返回this对象。

还是不清楚？我们来解释一下。首先，来看看对象中的this关键字有什么用。
<pre rel="JavaScript" class="prettyprint">var city = {
  name: 'beijing',
  getName: function() {
    return this.name;
  }
}
console.log(city.getName());</pre>
以上代码输出的城市名是beijing，说明this引用的是city对象。

再进一步，如果我们返回的是整个对象呢？
<pre rel="JavaScript" class="prettyprint">var num = {
  value: 1,
  minus: function (n) {
   this.value -= n;
   return this;
  },
  plus: function (n) {
    this.value += n;
    return this;
  },
  getVal: function () {
    console.log(this.value);
  }
};

num.minus(2).plus(5).getVal();</pre>
这样，就可以把方法调用连缀起来了。

<strong>3.jQuery.fn</strong>

在core.js中，我们可以看到这行代码：
<pre rel="JavaScript" class="prettyprint">jQuery.fn = jQuery.prototype = {
  //...
}</pre>
在我们开发jQuery插件时，经常要用到$.fn，也就是jQuery.fn。现在知道了吧，jQuery插件其实就是添加到jQuery.prototype的方法。正因为如此，插件里也不要忘了返回this噢。
<pre rel="JavaScript" class="prettyprint">(function( $ ){
  $.fn.fontcolor = function() {
    return this.each(function() {
      $(this).css("color", "orange");
    });
  };
})( jQuery );</pre>

<h2>系列其他文章</h2>
<ul>
    <li><a href="http://w3ctech.com/p/1183" title="解码jQuery系列5 – OOP与jQuery" target="_blank">解码jQuery系列5 – OOP与jQuery</a></li>
    <li><a href="http://w3ctech.com/p/881" title="解码jQuery系列3 – 原型" target="_blank">解码jQuery系列3 – 原型</a></li>
    <li><a href="http://w3ctech.com/p/843" title="解码jQuery系列2 – 对象" target="_blank">解码jQuery系列2 – 对象</a></li>
    <li><a href="http://w3ctech.com/p/812" title="解码jQuery系列1 - 变量和函数" target="_blank">解码jQuery系列1 - 变量和函数</a></li>
</ul> ]]></description>
            <pubDate>2012年02月09日</pubDate>
        </item>
                <item>
            <title>解码jQuery系列3 – 原型</title>
            <link>http://www.w3ctech.com/p/881</link>
            <guid>http://www.w3ctech.com/p/881</guid>
            <category>前端技术</category>
            <description><![CDATA[ <a href="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png"><img class="alignnone size-full wp-image-819" title="decoding-jquery" src="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png" alt="" width="272" height="133" /></a>
<a href="http://www.weibo.com/shichuan86">石川</a>著, <a href="http://www.weibo.com/lisf">李松峰</a>编译
              
“OOP与jQuery”是“解码jQuery”系列中的一个子系列，主要讨论 jQuery 的内部构成及相关的OOP（Object Oriented Programming，面向对象编程）概念。

第一篇文章以 jQuery 代码为例解释了变量（数据）和函数的概念。第二篇文章通过 jQuery 介绍了对象。

在这篇文章中，我们来谈一谈原型（prototype）。因为 JavaScript 是基于原型的语言，所以原型是这门语言中的一个非常重要的概念。那基于类的语言呢？这篇文章会不会比较它和基于原型的语言？不会，至少现在不会。我觉得要理解原型，不一定非要对类和原型进行比较。假如你想教人说日语，那不一定要让他先学会希腊语。当然，这个人掌握了日语之后，对他学希腊语肯定是有帮助的 :) 下面就来看一看什么是原型，以及jQuery怎么使用原型。

<strong>1.每个函数都有一个原型，原型是对象</strong>

可以在 JavaScript 控制台中测试 core.js 文件：
<pre rel="JavaScript" class="prettyprint">
var jQuery = function( selector, context ) {
    //...
}
console.log(typeof jQuery.prototype);

// 返回对象
</pre>

<strong>2.给原型添加方法和属性</strong>

给函数添加方法和属性的一种常见方式是像下面这样：
<pre rel="JavaScript" class="prettyprint">
jQuery.prototype.constructor = jQuery;
jQuery.prototype.init = function( selector, context, rootjQuery ) {
    //...
}
</pre>
jQuery的原型（大约在core.js的第78行）就保存在jQuery函数的prototype属性中，提取出来的话，就像下面这样（第78行代码中实际上还有一个 jQuery.fn，它只不过是 jQuery.prototype 的别名而已；为了简单起见，就把它先忽略吧）：
<pre rel="JavaScript" class="prettyprint">
jQuery.prototype = {
    constructor: jQuery,
    init: function( selector, context, rootjQuery ) {
      //...
    }
}
</pre>
对以上jQuery代码而言，它其实是用一个新对象完全重写和替换了最初的原型。那么，逐个给原型添加属性与完全重写原型有什么区别吗？没有什么太大区别，这就像是一个意思的两种不同表达方式，比如：

我可以说：我有一只绿色的猫，一只蓝色的猫和一只粉红色的猫。
也可以说：我有三只猫，分别是绿色的、蓝色的和粉红色的。

实际上还有第三种为函数添加属性和方法的方式：
<pre rel="JavaScript" class="prettyprint">
function jQuery() {
    this.constructor= jQuery;
    this.init= function( selector, context, rootjQuery ) {
      //...
    }
}
</pre>
<strong>3.使用原型的方法和属性</strong>

要使用方法和属性，必须创建一个新对象。以下就是在jQuery中创建新对象的方式，大约是在第6行：
<pre rel="JavaScript" class="prettyprint">
new jQuery.fn.init( selector, context, rootjQuery );
</pre>
另外，大约在第303行，还有如下代码：
<pre rel="JavaScript" class="prettyprint">
jQuery.fn.init.prototype = jQuery.fn;
</pre>
哎呀，jQuery函数、对象、jQuery.fn、原型，还有init之间是什么关系呢？

<strong>下一篇……</strong> 
下一篇，我们将继续探索jQuery核心，介绍jQuery.fn、原型和init方法之间的关系。
<pre rel="JavaScript" class="prettyprint">
var jQuery = function( selector, context ) {
    // jQuery对象实际上就是一个“增强版的”init构造函数
    return new jQuery.fn.init( selector, context, rootjQuery );
}
jQuery.fn = jQuery.prototype = {
    init: function( selector, context, rootjQuery ) {
      //...
    }
}
// 为 init 函数赋予 jQuery 原型，以方便后面实例化
jQuery.fn.init.prototype = jQuery.fn;
</pre>

<strong>推荐阅读</strong>
Stoyan Stefanov 编著的 Object-Oriented JavaScript 是一本最容易看懂的 OOP JavaScript 图书。

<h2>系列其他文章</h2>
<ul>
    <li><a href="http://w3ctech.com/p/1183" title="解码jQuery系列5 – OOP与jQuery" target="_blank">解码jQuery系列5 – OOP与jQuery</a></li>
    <li><a href="http://w3ctech.com/p/935" title="解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn" target="_blank">解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn</a></li>
    <li><a href="http://w3ctech.com/p/843" title="解码jQuery系列2 – 对象" target="_blank">解码jQuery系列2 – 对象</a></li>
    <li><a href="http://w3ctech.com/p/812" title="解码jQuery系列1 - 变量和函数" target="_blank">解码jQuery系列1 - 变量和函数</a></li>
</ul> ]]></description>
            <pubDate>2012年01月19日</pubDate>
        </item>
                <item>
            <title>JavaScript闭包详解【2】</title>
            <link>http://www.w3ctech.com/p/864</link>
            <guid>http://www.w3ctech.com/p/864</guid>
            <category>前端技术</category>
            <description><![CDATA[ <blockquote>之前在交流会上，和杜欢讨论过闭包的一些小东西，这里的文章主要还是从闭包产生的结果切人，讲述闭包的一些妙用，不探讨闭包产生的原因</blockquote>
<h2>函数参数的嵌入</h2>
函数参数的嵌入技术，原文是"Partially Applying Functions"，是一种在函数执行前，对其增加参数的方法。事实上，这个方法让你调用了一个新的函数。

注：assert是qunit单元测试所用的方法，第一个参数若为true则输出第二个参数，通常true表示执行结果为预期的值，下面都用到了assert对结果进行校验
<pre rel="JavaScript" class="prettyprint">String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = ("John, Resig, Boston").csv();
assert( results[1] == "Resig", "字母切分成功" );</pre>
partial方法就是能够实现partially apply的函数，我们可以看到虽然csv在调用的时候没有带任何参数，但是还是按照/,\s*/进行split了。

prototype框架里有一个curry函数，和partial比较类似。
<pre rel="JavaScript" class="prettyprint">Function.prototype.curry = function() {
  var fn = this, args = Array.prototype.slice.call(arguments);
  return function() {
    return fn.apply(this, args.concat(
      Array.prototype.slice.call(arguments)));
 };
};</pre>
通过闭包的使用，我们将this变量和args变量保存下来，并可以让返回的函数能够访问到，在返回的函数中，我们将本身的参数和保存下的args参数进行合并，也就做到了嵌入参数的功能。

curry函数看起来很妙，但是我们还可以做的更好。如果我们需要将一些参数保留给可能传入的函数，那么就需要做一些更多的处理。
<pre rel="JavaScript" class="prettyprint">Function.prototype.partial = function(){
 var fn = this, args = Array.prototype.slice.call(arguments);
 return function(){
  var arg = 0;
  for ( var i = 0; i &lt; args.length &amp;&amp; arg &lt; arguments.length; i++ )
   if ( args[i] === undefined )
    args[i] = arguments[arg++];
  return fn.apply(this, args);
 };
};</pre>
我们通过将预设参数中的undefine值替换为传入的函数，从而实现了一个更方便的参数嵌入函数。看几个实用的例子。
<pre rel="JavaScript" class="prettyprint">//delay函数的实现
var delay = setTimeout.partial(undefined, 10);
delay(function(){
 assert( true, "函数延迟调用成功" );
});</pre>
<pre rel="JavaScript" class="prettyprint">//事件绑定的实现
var bindClick = document.body.addEventListener
 .partial("click", undefined, false);
bindClick(function(){
 assert( true, "当前函数绑定了click事件" );
});</pre>
这个技术的主要目的函数缩小代码的复杂度，让API的使用更加方便清晰。

对闭包的产生和原理感兴趣的同学，可以看下<a href="http://www.otakustay.com/closure-ppt/">http://www.otakustay.com/closure-ppt/</a>。

本文翻译自《Secrets_of_the_JavaScript_Ninja》 ]]></description>
            <pubDate>2012年01月17日</pubDate>
        </item>
                <item>
            <title>解码jQuery系列2 – 对象</title>
            <link>http://www.w3ctech.com/p/843</link>
            <guid>http://www.w3ctech.com/p/843</guid>
            <category>前端技术</category>
            <description><![CDATA[ <a href="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png"><img class="alignnone size-full wp-image-819" title="decoding-jquery" src="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png" alt="" width="272" height="133" /></a>
<a href="http://www.weibo.com/shichuan86">石川</a>著, <a href="http://www.weibo.com/lisf">李松峰</a>编译

“OOP与jQuery”是“解码jQuery”系列中的一个子系列，主要讨论 jQuery 的内部构成及相关的OOP（Object Oriented Programming，面向对象编程）概念。

在<a href="http://w3ctech.com/b/archives/812" target="_blank">上一篇</a>中，我们以 jQuery 代码为例解释了变量（数据）和函数的概念。本篇将通过 jQuery 来介绍对象。

<strong>1.对象就是对象，跟人和椅子一样</strong>
既然我们讨论的是面向对象编程，那对象是什么呢？对象就是对象，比如苍井空老师就是一个对象，桌椅或狗也是对象。所谓面向对象，不过就是用编程语言来表示对象而已。

如上所述，那么 shichuan 就是一个对象。因此在 OOP 中，可以用一个对象来表示他：
<pre rel="JavaScript" class="prettyprint">var shichuan = {};</pre>
每个对象，都可以有属性和方法（行为）。比如，shichuan 的头发是黑色的，这就是他的属性。因为天生就是黑色的，他不用时不时地把头发染黑，所以它不是方法（行为）。我们可以把这个属性添加到 shichuan 对象中：
<pre rel="JavaScript" class="prettyprint">var shichuan = {
    hair: "black"
};</pre>
好了，假设 shichuan 有一个特长是骑独角兽，那么骑独角兽（riding unicorn）就是他的一个方法（行为）。用 OOP 来表示，就是这样：
<pre rel="JavaScript" class="prettyprint">var shichuan = {
    hair: "black",
    ridingUnicorn: function() {
        // 我怎么骑独角兽
    }
};</pre>
总结一下对象的概念：

包含对象的变量名叫 shichuan
对象的内容被包含在 { 和 } 中
对象的元素（属性和方法）用逗号来分隔
键/值对用冒号分隔，比如 key : value（或者上面例子中的 hair : "black"）
方法实际上也是函数，比如 ridingUnicorn 就是对象 shichuan 的一个方法，行为（函数）

<strong>2.jQuery 中的对象</strong>
那么，jQuery 中是怎么使用对象的呢？还记得我们在第一篇文章里谈到的 jQuery 函数的局部副本吧。下面我们就看看 jQuery 函数的内部（大约在第4行），实际上这个函数里只有一行代码，其注释说：jQuery 对象实际上就是一个“增强版的”init构造函数。那这个增强的 init 是什么样呢？
<pre rel="JavaScript" class="prettyprint">var jQuery = function( selector, context ) {
    // jQuery对象实际上就是一个“增强版的”init构造函数
    return new jQuery.fn.init( selector, context, rootjQuery );
}</pre>
如果你在代码里搜索“jQuery.fn”，在大约第76行可以找到它，大致是这样的：
<pre rel="JavaScript" class="prettyprint">jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    init: function( selector, context, rootjQuery ) {
    ...
    },
    ...
}</pre>
jQuery的原型（下一篇文章将介绍原型）——jQuery.prototype，是一个对象，一个大对象。这个对象有很多很多属性和方法。比如，它的属性有 constructor、selector、jquery、length，等等；它的方法有 init、size、toArray、get、pushStack，等等。

<strong>3.函数是数据，也是对象</strong>
在第一篇文章中，我们说过函数就是数据，通过以下两种方式定义jQuery函数，结果是相同的：
<pre rel="JavaScript" class="prettyprint">// 局部 jQuery
function jQuery( selector, context ){
    //...
}
// 局部 jQuery
var jQuery = function( selector, context ){
    //...
}</pre>
实际上，还有第三种方法：

// 局部 jQuery
<pre rel="JavaScript" class="prettyprint">var jQuery = new Function('selector', 'context', '//...');</pre>
在OOP中，使用 new 加构造函数（这里的 Function）是创建新对象的典型方式。虽然这种方法也能创建函数，但通常并不是最好的方式，因为 JavaScript 会使用 eval 对传入的源代码进行求值。

<strong>下一篇……</strong>
下一篇，我们将继续探索jQuery核心，介绍原型。

<strong>推荐阅读</strong>
Stoyan Stefanov 编著的 Object-Oriented JavaScript 是一本最容易看懂的 OOP JavaScript 图书。

<h2>系列其他文章</h2>
<ul>
    <li><a href="http://w3ctech.com/p/1183" title="解码jQuery系列5 – OOP与jQuery" target="_blank">解码jQuery系列5 – OOP与jQuery</a></li>
    <li><a href="http://w3ctech.com/p/935" title="解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn" target="_blank">解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn</a></li>
    <li><a href="http://w3ctech.com/p/881" title="解码jQuery系列3 – 原型" target="_blank">解码jQuery系列3 – 原型</a></li>
    <li><a href="http://w3ctech.com/p/812" title="解码jQuery系列1 - 变量和函数" target="_blank">解码jQuery系列1 - 变量和函数</a></li>
</ul> ]]></description>
            <pubDate>2012年01月14日</pubDate>
        </item>
                <item>
            <title>解码jQuery系列1 - 变量和函数</title>
            <link>http://www.w3ctech.com/p/812</link>
            <guid>http://www.w3ctech.com/p/812</guid>
            <category>前端技术</category>
            <description><![CDATA[ <a href="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png"><img src="http://w3ctech.com/b/wp-content/uploads/2012/01/decoding-jquery.png" alt="" title="decoding-jquery" width="272" height="133" class="alignnone size-full wp-image-819" /></a>
<a href="http://www.weibo.com/shichuan86">石川</a>著, <a href="http://www.weibo.com/lisf">李松峰</a>编译 

光开放源代码是不够的。为了让开源进一步开放，在“解码jQuery”系列中，我们会剖析jQuery的每一个方法，领略jQuery框架之美，同时向这个框架背后的天才们致敬。

“OOP与jQuery”是“解码jQuery”系列中的一个子系列，主要讨论jQuery的内部构成及相关的OOP（Object Oriented Programming，面向对象编程）概念。

学习OOP概念的最佳方式，就是剖析一个真实的框架。学习某个框架的最佳方式，就是领会其中的OOP概念。

jQuery在整合压缩前是分为很多不同文件的。它的源代码可以在github的<a href="https://github.com/jquery/jquery/tree/master/src" target="_blank">这页</a>看到。 jQuery core （在<a href="https://github.com/jquery/jquery/blob/master/src/core.js" target="_blank">core.js</a>里）是jQuery的核心。面向对象有5个重要的概念：变量（数据），函数，对象，原型和继承。这些是JS语言面向对象的基础，也是jQuery的基础。

jQuery核心（core.js）是jQuery的“大脑”，其中涉及五个重要概念：变量（数据）、函数、对象、原型和继承。这五个方面是jQuery核心的五个“脑叶”，又是探求OOP概念的五个“意识”。

整个jQuery库都浓缩在一个jQuery变量中。实际上，core.js中有两个jQuery变量（var jQuery），一个是全局的，另一个是局部的。今天我们就通过jQuery来了解JavaScript中的变量和函数这两个概念。下面就是刚提到的两个jQuery变量：

<pre rel="JavaScript" class="prettyprint">
// 全局 global jQuery 
var jQuery = (function() {
  // 局部 local jQuery
  var jQuery = function( selector, context ) {
    // ...
  }
})();
</pre>

<strong>1. 变量保存数据，函数也是数据</strong>
我们先来看一看局部的jQuery：
<pre rel="JavaScript" class="prettyprint">
// 局部 local jQuery
var jQuery = function( selector, context ) {
  //...
}
</pre>

JavaScript中的函数实际上是数据。也就是说，通过以下两种方式定义jQuery函数，结果是相同的：
<pre rel="JavaScript" class="prettyprint">
// 局部 local jQuery
function jQuery( selector, context ){
  //...
}
// 局部 local jQuery
var jQuery = function( selector, context ){
  //...
}
</pre>

<strong>2. 函数可以匿名</strong>
再来看一看全局的jQuery：
<pre rel="JavaScript" class="prettyprint">
// 全局 global jQuery
var jQuery = (function() {
  //...
})();
</pre>

从中把函数部分提取出来，就会发现它是匿名的：
<pre rel="JavaScript" class="prettyprint">
function() {
  //...
}
</pre>

在JavaScript中，可以不把数据赋值给变量，而数据照样可以存在。比如，下面这个字符串可以存在于JavaScript代码中，而且不会返回任何错误：

<pre rel="JavaScript" class="prettyprint">"我是数据，我不会导致错误。"</pre>

前面第1点提到了“函数是数据”，因此函数也可以独立存在，而不需要被赋值给某个变量。假如你运行上面的匿名函数，它100%可以运行，而且不会导致任何错误。那匿名函数有什么用呢？下一点就来回答这个问题。

<strong>3. 匿名函数可以自调用</strong>
匿名函数的一个优点是可以作为自调用的函数来使用。举个例子，下面的函数在页面加载时会自动执行，你可以在控制台看到输出：

<pre rel="JavaScript" class="prettyprint">
var jQuery = (function() {
  console.log("我是自调用。");
})();
</pre>

那为什么要像这样来使用匿名函数呢？因为这样可以在不创建全局变量的情况下执行一些内部操作。jQuery使用匿名自调用函数来完成它的一次性初始化。

<strong>下一期…</strong>
下一篇，我们将继续探索jQuery核心，介绍原型和对象的概念。

<h2>系列其他文章</h2>
<ul>
    <li><a href="http://w3ctech.com/p/1183" title="解码jQuery系列5 – OOP与jQuery" target="_blank">解码jQuery系列5 – OOP与jQuery</a></li>
    <li><a href="http://w3ctech.com/p/935" title="解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn" target="_blank">解码jQuery系列4 – 函数作用域、jQuery连缀模式和jQuery.fn</a></li>
    <li><a href="http://w3ctech.com/p/881" title="解码jQuery系列3 – 原型" target="_blank">解码jQuery系列3 – 原型</a></li>
    <li><a href="http://w3ctech.com/p/843" title="解码jQuery系列2 – 对象" target="_blank">解码jQuery系列2 – 对象</a></li>
</ul> ]]></description>
            <pubDate>2012年01月11日</pubDate>
        </item>
                <item>
            <title>使用Coffeescript编写jQuery插件</title>
            <link>http://www.w3ctech.com/p/802</link>
            <guid>http://www.w3ctech.com/p/802</guid>
            <category>前端技术</category>
            <description><![CDATA[ 如果你知道jQuery和Coffeescript，要编写一个jQuery插件是很容易的。 

我们将通过写一个jQuery的插件，它会允许我们为表中的行添加交替颜色交替。

这里是整个插件：

<pre rel="JavaScript" class="prettyprint">$ = jQuery
$.fn.zebraTable = (options) ->
    defaults = 
        evenColor: '#ccc'
        oddColor : '#eee'

    options = $.extend(defaults, options)
    @each ->
        $("tr:even", this).css('background-color', options.evenColor)
        $("tr:odd" , this).css('background-color', options.oddColor)</pre>

让我们看看它是怎么执行的：
<ol>
<li>我们把为$绑为jQuery对象。</li>
<li>我们创建了一个匿名函数并添加到jQuery$，分配给fn.zebraTable。</li>
<li>在此之后，我们将能够做$（“选择”）。zebraTable（）或`$（选择）。zerbraTable（optionsDict）</li>
<li>此功能将设置交替行的背景颜色。</li>
</ol>

<pre rel="JavaScript" class="prettyprint">(function() {
  var $;

  $ = jQuery;

  $.fn.zebraTable = function(options) {
    var defaults;
    defaults = {
      evenColor: '#ccc',
      oddColor: '#eee'
    };
    options = $.extend(defaults, options);
    return this.each(function() {
      $("tr:even", this).css('background-color', options.evenColor);
      return $("tr:odd", this).css('background-color', options.oddColor);
    });
  };

}).call(this);</pre>

你可以这样调用它。

<pre rel="JavaScript" class="prettyprint">$(function() {
  $("table").zebraTable(  {
      evenColor: 'red',
      oddColor: 'yellow'
    });
});</pre>

显着特点：
<ol>
<li>由于Coffeescript将代码括在函数里, $= jQuery不覆盖一切，没有必要附上自己的封闭的插件。</li>
<li>插件里面的this是指选定的jQuery对象，所以也没有必要用$(this)。</li></ol>

<strong>参考</strong>
翻译自 <a href="http://agiliq.com/blog/2012/01/writing-jquery-plugins-using-coffeescript/">http://agiliq.com/blog/2012/01/writing-jquery-plugins-using-coffeescript/</a> ]]></description>
            <pubDate>2012年01月07日</pubDate>
        </item>
                <item>
            <title>OYE - AMD模块化开发思想的实现原理及应用</title>
            <link>http://www.w3ctech.com/p/774</link>
            <guid>http://www.w3ctech.com/p/774</guid>
            <category>JavaScript</category>
            <description><![CDATA[ 为了推行模块话的开发思想，将刚推出不久的<a href="http://www.w3cgroup.com/oye" target="_blank">AMD模块化加载管理器</a> - <a href="http://www.w3cgroup.com/oye/" target="_blank">OYE</a>，拿出来跟大家分享一下，希望能够多尽一份力!

<a href="http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition" target="_blank">AMD</a>是<a href="http://wiki.commonjs.org/wiki/CommonJS" target="_blank">CommonJS</a>规范的一个分支，它更适合在浏览器端进行实现。

<a href="http://www.w3cgroup.com/oye/" target="_blank">OYE</a>是对<a href="http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition" target="_blank">AMD规范</a>的一个实现!

<h2>OYE概述</h2>
<ul>
    <li>✔ 目标单纯，只做模块化，超轻量</li>
    <li>✔ 不依赖Script onload事件，更稳定可靠</li>
    <li>✔ 完美支持具名、匿名模块</li>
    <li>✔ 支持模块提取完整依赖列表</li>
    <li>✔ 支持模块循环依赖检测</li>
    <li>✔ 支持require与define在同一个文档</li>
</ul>
<h2>OYE实现原理</h2>

<h3>辅助项</h3>
[[当前正在处理的模块名称]], [[请求队列]]

<h3>define</h3>
define函数执行时，如果是具名模块，则直接将模块定义体与模块名进行注册；如果是匿名模块，则取[[当前正在处理的模块名称]]为模块名称进行模块注册；最后将[[当前正在处理的模块名称]]置空；

<h3>require</h3>
require函数执行时，如果[[当前正在处理的模块名称]]为空，则发起文件请求，并将本次请求的模块名称置为[[当前正在处理的模块名称]]；否则，将本次请求丢到[[请求队列]]

<h3>依赖关系</h3>
采用触发器方式，一个模块准备好后，触发所有依赖它的模块进行检查，看它们是否也准备好

<h2>应用指引</h2>

<h3>开发阶段</h3>

确认当前项目准备采用模块化的方式进行开发；
每个模块定义为匿名模块，并存储为一个独立的JS文件；
每个页面最好只引入一个模块，如：首页，可以有一个app/home这样的模块，在这个模块中再去调用其他模块，如：
<pre rel="JavaScript" class="prettyprint">
&lt;你的站点路径或CDN路径&gt;resource/js/app/home.js
define(['common/head','common/foot','app/home/content'], 
function(head,foot,content){
    return {
        init:function(){
        head.init();
        foot.init();
        content.init();
    }
};
});
</pre>

然后，在home页面，我们只要这样去调用即可：

<pre rel="JavaScript" class="prettyprint">
&lt;script src="&lt;你的站点路径或CDN路径&gt;resource/js/oye/oye.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
require('app/home', function(home){
    home.init();
});
&lt;/script&gt;
</pre>
请注意：

模块文件home.js与oye.js的目录关系，在oye里，模块名对应模块的路径！
如果模块名是以http或https等协议开头的，则视为绝对路径，oye会直接去请求这个URL；
否则，都被视为相对路径，相对于oye.js所在的路径而言，而不是相对于当前页面的路径，这个很重要！

为什么设计成这样？

因为我们需要覆盖线上线下两种应用场景：
线下，即开发阶段，我们的资源文件与项目内容基本上是作为一个项目的整体来开发的；
线上，资源文件和项目内容多数情况下会分开部署到不同的域；

更多具体用法，请参见我们给出的 <a href="http://www.w3cgroup.com/oye/" target="_blank">OYE DEMO演示</a> ！

<strong>项目上线(可选)</strong>
如果公司的站点线上与开发阶段完全不一致，则需要考虑以下步骤。

在BUILD工具中添加提取JS模块依赖列表、合并压缩的功能；实现方式大致如下：
通过对模块依赖列表的提取，将各依赖模块的模块名自动添加到提取出来的内容中，即为原来的匿名模块加上模块名称，如：
(举例)我们通过对app/home提取依赖列表，可以得到：

app/home: http://你的站点路径/resource/js/app/home.js
common/head: http://你的站点路径/resource/js/common/head.js
common/foot: http://你的站点路径/resource/js/common/foot.js
app/home/content: http://你的站点路径/resource/js/app/home/content.js

现在，我们的BUILD工具就可以遍历读取这些文件，并将读取的内容做如下替换：
将 define( 替换成 define("app/home" ，即将模块名填充进去。
将已知的具名模块配置中，添加一条：define.amd.namedModules['模块名'] = true;
将提取并修改后的所有内容保存到一个JS文件，如：app/home.min.js
在页面上，引入oye.min.js文件的后面，添加一个对该文件的引入：&lt;script src="&lt;你的站点路径或CDN路径&gt;resource/js/app/home.min.js"&gt;&lt;/script&gt;

<a href="http://www.w3cgroup.com/oye/" target="_blank">现在就去体验使用OYE作为模块化开发的便利吧！</a> ]]></description>
            <pubDate>2011年12月21日</pubDate>
        </item>
                <item>
            <title>JavaScript闭包详解【1】</title>
            <link>http://www.w3ctech.com/p/763</link>
            <guid>http://www.w3ctech.com/p/763</guid>
            <category>前端技术</category>
            <description><![CDATA[ 闭包就是一种在函数内访问和操作外部变量的方式，一般情况下，我们会在函数外部定义一些变量以供函数内部使用。
<pre rel="JavaScript" class="prettyprint">var a = 1;
function fn( arg ){
 var b =2;
 function fnInner ( arg ){
 console.log(a); //访问全局的变量
 console.log(b); //访问外部函数体内的变量
 console.log(arg); //访问函数自身的变量
 }
 fnInner(3);
}</pre>
fn函数的闭包引用了变量b，还有函数本身。fnInner函数引用了b，a，传递给它的参数。我们需要注意一点，虽然函数并没有特别创建一个变量来保存这些要引用的数据，但是要保存和引用这些变量还是会带来内存的消耗。
<h2>私有变量</h2>
JavaScript语言本身并没有提供创建私有变量的方式，但是我们知道，函数外的变量是无法访问函数内部的变量的，这意味着我们可以这样创建私有变量：
<pre rel="JavaScript" class="prettyprint">
function(){
 this.public = 1; //public在函数外面可以访问
 var private = 1;//private变量在函数外部无法访问
}</pre>
<h2>回调函数和定时器</h2>
有时候我们会这样写一个回调函数
<pre rel="JavaScript" class="prettyprint">
var a = 1;
jQuery.ajax({
 url : "test.html",
 success : function(html){
 console.log(a);
 }
})</pre>
类似的的还有在设置定时器的时候，我们在1000ms后将一个函数插入队列等待执行
<pre rel="JavaScript" class="prettyprint">var a = 1;
setTimeout(function(){
 console.log(a);
},1000);
a = a + 1;</pre>
ajax回调里的结果可能比较容易猜到，匿名函数本身是一个闭包，保存了变量a的值，从而可以访问。而第二个定时器回调主要要说明的就是，闭包所引用的值是在执行期生成的，而我们虽然在a = a+1前面定义了匿名函数，但是执行的时候因为匿名函数被插入到执行队列的尾部，那么a = a +1会先执行，然后在执行匿名函数，也就是说这个例子返回的值为2。
<h2>改变闭包的context</h2>
有这么一段代码
<pre rel="JavaScript" class="prettyprint">
var Button = {
  click: function(){
    console.log(this);
    this.clicked = true;
  }
};
var elem = document.querySelector("body");
elem.addEventListener("click", Button.click, false);</pre>
我们的目的是通过点击body来改变Button对象的clicked值，但是失败了

虽然我们在定义的时候试图让this指向了Button，但是在addEventListener之后，this又被指向到elem。

解决方法有很多。

在支持Function.prototype.bind方法的浏览器里，我们只需要简单地修改一下代码即可
<pre rel="JavaScript" class="prettyprint">var Button = {
  click: function(){
    console.log(this);
    this.clicked = true;
  }
};
var elem = document.querySelector("body");
elem.addEventListener("click", Button.click.bind(Button), false);</pre>
注：Function.prototype.bind方法参考ECMAScript 262 15.3.4.5中的说明，作用和apply类似，但是不会执行原函数

如果不支持Function.prototype.bind，那么，我们可以自己实现一个bind函数。
<pre rel="JavaScript" class="prettyprint">function bind(context, name){
  return function(){
    return context[name].apply(context, arguments);
  };
}
var Button = {
  click: function(){
    console.log(this);
    this.clicked = true;
  }
};
var elem = document.querySelector("body");
elem.addEventListener("click", bind(Button, "click"), false);</pre>
本文参考自John Resign的《secrets of the JavaScript ninjia》 ]]></description>
            <pubDate>2011年12月17日</pubDate>
        </item>
                <item>
            <title>如何用nodejs做一个简单的前端Static Server</title>
            <link>http://www.w3ctech.com/p/749</link>
            <guid>http://www.w3ctech.com/p/749</guid>
            <category>nodeJS</category>
            <description><![CDATA[ 最近在学习nodejs相关的一些知识，动手练永远是进步最快的，业余时间搞了个土鳖项目，叫nodeCombo，主要功能可以参见github地址：<a href="https://github.com/xiaojue/node-combo" target="_blank">https://github.com/xiaojue/node-combo</a>

目前版本不太稳定，争取年前把TODO都完成，再补上测试，最后发布到NPM上。现在的版本如果有人要下，建议用在测试开发环境，有任何bug可以提交给我或者直接帮我重写一下……感激不尽。

下面介绍一下主要的实现思路，API相关可以直接看README。

nodejs的module基本结构可以参考这里：<a href="http://nodejs.org/docs/latest/api/modules.html#addenda_Package_Manager_Tips" target="_blank">http://nodejs.org/docs/latest/api/modules.html#addenda_Package_Manager_Tips</a>

我这个module目录下主要是这么几个文件：

<a href="http://w3ctech.com/b/wp-content/uploads/2011/12/tree.jpg"><img class="alignnone size-full wp-image-750" src="http://w3ctech.com/b/wp-content/uploads/2011/12/tree.jpg" alt="" width="187" height="296" /></a>

代码写的都很屎。逐一简单介绍一下吧。

combo,image,resize,template是分别负责合并文本文件，图片文件，重绘图片大小和实现简单的静态模板等功能。

config是进行combo的配置文件，对目录和文件扩展名之类进行了统一控制。

range是实现http中的range响应。

tools是几个可能会通用的工具函数。

requires文件是一个小hack，可以避免少些点require，一会下面介绍。

handle文件是处理http响应的。

server是启动文件。

具体代码可以直接去看文件了，下面开始说实现思路。

如果你对http请求不熟悉，可以参见这里：<a href="http://zh.wikipedia.org/wiki/Http%E5%8D%8F%E8%AE%AE#.E4.BE.8B.E5.AD.90" target="_blank">http://zh.wikipedia.org/wiki/Http%E5%8D%8F%E8%AE%AE#.E4.BE.8B.E5.AD.90</a>

用nodejs实现一个非常简单，比如我的combo模块需要暴露给外部一个run的方法：
<pre rel="nodeJS" class="prettyprint">exports.run = function(){
var host = config.list.host,
port = config.list.port,
server = http.createServer(handle.run);
server.listen(port);
console.log('server on ' + port);
}</pre>
这样一来所有的配置端口的http请求就全部都进到handle.run这个方法里了。那么我在handle.run里要进行各种处理，比如分析请求头的请求文件名字（URL里的filename和filepath），还有比如静态服务器都支持的gzip，range请求，并且返还给浏览器Expires，Cache-Control，Last-Modified，gizp，range等对应信息或者结果。

handle文件写的太屎了，代码也比较长，这是需要重构的，基本的流程就是接受请求，分析url和请求头信息，然后根据一些具体需要，分别交给具体的方法进行处理，比如我请求一个正常的jpg图片，就会直接找服务器对应地址的jpg文件，存在的话用Stream读取，然后返回结果给浏览器，并且附带上响应头。如果我请求的是css，js文件或者combo的js，css，jpg文件，我会根据不同的要求，分发给相应方法进行处理，比如图片就用nodejs的<a href="https://github.com/LearnBoost/node-canvas" target="_blank">node-canvas</a>进行拼合或者改大小，比如文本，我则会直接进行顺序拼接，再看需要不需要过一遍static模板，最后返回给浏览器。

大概实现思路就是这样。你给我服务器请求，我根据请求返回结果，（如果有特殊要求，我就做特殊处理之后再给你）。主要这些特殊需求都是围绕提高前端生产力来的，所以也可以说是一个前端用着比较舒服的static server吧。

最后说一下我那个requires文件，写过nodejs的都知道，我们总要在每个js文件头部写很多这样的代码：
<pre rel="nodeJS" class="prettyprint">var fs=require("fs"),
    path=require('path'),
    readline=require('readline')....</pre>
用了requires文件，只需要require一次，然后GlobalInit一下就好了，具体可以查看我每个js文件的开头部分。

好了，目前已经实现的例子和用法，文档已经给出，有兴趣可以仔细去看，或者联系我。

下周应该会把less和coffeescript的默认支持也调通，然后再增加combo功能（其实多此一举，less带import的功能），所以也可能不对less支持。

嗯，希望这文章能对学习nodejs的同学有些帮助，有更多想法也可以联系我。 ]]></description>
            <pubDate>2011年12月16日</pubDate>
        </item>
                <item>
            <title>说说为什么 [] == ![] 为true</title>
            <link>http://www.w3ctech.com/p/738</link>
            <guid>http://www.w3ctech.com/p/738</guid>
            <category>前端技术</category>
            <description><![CDATA[ 此前在微博上无意中看到有人问<strong>“为什么alert([] == ![])会是true？”</strong>，

刚看到这个问题我也说不上来究竟是什么原因，只知道这个肯定又是和<strong>==</strong>操作相关的类型转换问题。

于是，就翻开了<a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" target="_blank"><strong>“葵花宝典（ECMA-262-5th）”</strong></a>，你懂的。

在宝典的帮助下，我尝试着来解释下该问题的原因：
<ul>
	<li>首先看看<strong>==</strong>这个操作内部是如何工作的</li>
</ul>
宝典中的关于<strong>==</strong>操作的工作描述如下(11.9.1)：
<blockquote>The production EqualityExpression: <em>EqualityExpression</em> == <em>RelationalExpression</em> is evaluated as follows:

1. Let <em>lref</em> be the result of evaluating <em>EqualityExpression</em>

2. Let <em>lval</em> be GetValue(<em>lref</em>)

3. Let <em>rref</em> be the result of evaluating <em>RelationalExpression</em>

4. Let <em>rval</em> be GetValue(<em>rref</em>)

5. Return the result of performing abstract equality comparison <em>rval==lval</em></blockquote>
<ul>
	<li>根据上面的步骤，我们来对问题作如下解析：</li>
</ul>
<ol>
	<li>先求GetValue([])</li>
	<li>再求GetValue(![])</li>
	<li>最后求 GetValue([]) == GetValue(![])</li>
</ol>
先要搞清楚GetValue方法是干嘛的，继续看宝典关于GetValue的描述(8.7.1)：
<blockquote>
<ol>
	<li>If Type(V) is not Reference, return V</li>
	<li>….</li>
</ol>
</blockquote>
对于解释我们的问题，看到这里就足够了，因为[]和![]都不属于Reference，所以，GetValue([])和GetValue(![])都返回自身。

这里关于什么是Reference不想再赘述了，要详细了解的可以看宝典（8.7）。

那么，上述问题进一步转化成了如下问题：
<ol>
	<li>GetValue([])为 []</li>
	<li>GetValue(![])为 false， （这里！会使得[]强制转化为Boolean类型）</li>
	<li>这里就成了求 <strong>[] == false</strong>的问题</li>
</ol>
也就是说： <strong>[] == ![]</strong> 现在转化为了 <strong>[] == false</strong>。
<ul>
	<li>根据”abstract equality comparison”算法来求结果：</li>
</ul>
宝典中第五步就提到了根据”abstract equality comparison”来求最后的结果。
现在先来看看[]和false的类型，两者类型显而易见，前者是Object,后者Boolean。

然后，我们进一步来看看这个算法是如何的(11.9.3)，以下只列出了和我们这个问题相关的算法步骤,其中有这么一条：
<blockquote>The comparison x == y, where x and y are values, produces <strong>true</strong> or <strong>false</strong>. Such a comparison is performed as follows:

7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y)</blockquote>
这句话很容易理解，就是要把y转化类型为数值，也就是说false变为0。

这样以来，问题有变成了求： <strong>[] == 0</strong>

继续看宝典中这个算法(11.9.3)，其中有这么一条：
<blockquote>The comparison x == y, where x and y are values, produces <strong>true</strong> or <strong>false</strong>. Such a comparison is performed as follows:

9. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.</blockquote>
于是，问题有变成了求： <strong>ToPrimitive([]) == 0</strong>。
<ul>
	<li>查看ToPrimitive的工作机制（9.1）</li>
</ul>
其中对于Object有这种转换描述：
<blockquote>Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object,

passing the optional hint PreferredType. The behaviour of the

[[DefaultValue]] internal method is defined by this specification for all native
ECMAScript objects in 8.12.8.</blockquote>
继续顺藤摸瓜，看[[DefaultValue]](hint)，我们的例子中hint是Number，因为它是和0去做比较。

根据宝典（8.12.8）描述：
<blockquote>When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken:

1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument “valueOf”.

2. If IsCallable(valueOf) is true then

a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.

b. If val is a primitive value, return val.

3. Let toString be the result of calling the [[Get]] internal method of object O with argument “toString”.

a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.

b. If str is a primitive value, return str.

…</blockquote>
这里不对valueOf再去做赘述了，MDN上面有很<a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/ValueOf" target="_blank">简短的说明</a>,大致意思如下：
<blockquote>默认，每个对象都有从Object继承下来的valueOf方法。其中每个内置的核心对象都会重载该方法来返回正确的值，对于没有基础类型值的对象，则返回对象自身。</blockquote>
那么，对于我们的情况来说，进入了算法中的2，但是，因为val是对象不是基础类型，所以继续进入第3步，这个时候关键来了：
<strong>开始调用[]的toString方法，这个时候会返回""，一个空的字符串，因此ToPrimitive([])为""</strong>

因此，问题又转化成了：
<strong>"" == 0</strong>

现在答案就很明显了，根据宝典的==工作原理如下描述（11.9.3）：
<blockquote>The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.</blockquote>
好了，根据算法，会将""转化为数值类型，那么自然就变成了0，于是 0 == 0 是很自然而然的。

<strong>总结：</strong>

最终问题就从： <strong>[] == ![]</strong> 变成了 <strong>0 == 0</strong>。答案自然是<strong>true</strong>了。

其实遇到这种语言层面的问题，直接看宝典即可。

<strong>说明：</strong>

以上诸如 11.9.3 这样的数字均表示葵花宝典中的章节。
<h2>参考资料</h2>

<ul>
	<li><a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" target="_blank">葵花宝典（ECMA-262-5th）</a></li>
	<li><a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/ValueOf" target="_blank">MDN</a></li>
</ul> ]]></description>
            <pubDate>2011年12月09日</pubDate>
        </item>
                <item>
            <title>node.js开发的桌面应用TermKit介绍</title>
            <link>http://www.w3ctech.com/p/677</link>
            <guid>http://www.w3ctech.com/p/677</guid>
            <category>前端技术</category>
            <description><![CDATA[ 最近和团队翻译Node的书，《node web development》，同时也顺带好好学习了下nodejs。刚好展炎要搞个关于nodejs开发桌面应用的分享，就一起看了下相关的知识，那自然，就发现了TermKit这个标志性的应用。
<h2>TermKit介绍</h2>
【下面内容参考自<a href="http://acko.net/blog/on-termkit">http://acko.net/blog/on-termkit</a>】

长久以来，大家都习惯了在linux下使用terminal控制系统的方式

<a href="http://www.f2es.com"><img title="termkit" src="http://acko.net/files/termkit-1.png" alt="" width="525" height="290" data-markzhi="registered" /></a>

像我这样的超级不专业linux人士，是这样的

<a href="http://www.f2es.com/wp-content/uploads/2011/11/1.jpg"><img title="1" src="http://www.f2es.com/wp-content/uploads/2011/11/1.jpg" alt="" width="500" data-markzhi="registered" /></a>

这个时候，<a href="http://acko.net/" target="_blank">steven wittens</a>出现了，并为macox写了一个很有趣的东西，可以称之为下一代的富媒体终端。它可以在终端中用图形化元素来显示命令结果。

就像下面这样：

<a href="www.f2es.com"><img title="termkit" src="http://wowubuntu.com/wp-content/uploads/2011/06/termkit-2.png" alt="" width="530" height="435" data-markzhi="registered" /></a>

带自动补全，还有各种看起来很舒服的图标。

<a href="http://www.f2es.com"><img title="termkit" src="http://wowubuntu.com/wp-content/uploads/2011/06/termkit-5.png" alt="" width="468" height="446" data-markzhi="registered" /></a>
<h2>如何安装</h2>
在mac里怎么安装我就不介绍了，这里只介绍linux下的安装

首先，我们需要安装nodejs，这里要注意，推荐安装0.4.* stable版本，新版本可能会有不兼容的问题，不管你信不信，反正我装0.6.1的时候挂了。

还有就是connect的版本要在1.2.0到1.3.0之间，不包括1.3.0。

具体就是这样：
<pre rel="shell" class="prettyprint">wget http://nodejs.org/dist/node-v0.4.8.tar.gz
cd node-v0.4.8
tar -xf node-v0.4.8
./configure
make &amp;&amp; make install</pre>
安装好node之后安装npm
<pre rel="shell" class="prettyprint">curl http://npmjs.org/install.sh|sh</pre>
之后就是下载termkit并安装
<pre class="prettyprint">git clone https://github.com/Floby/TermKit.git --recursive
cd TermKit/
npm install</pre>
然后就可以启动了，这里要注意的是，我们需要在TermKit目录下进行启动操作：
<pre rel="shell" class="prettyprint">node Node/nodekit.js</pre>
启动后terminal里会显示运行的log，然后就可以把注意力放到浏览器上了。

当然，因为客户端是浏览器，服务端是node的情况下，socket.io就是一个必不可少的模块了，这些在npm安装的时候会按照依赖关系自动加载好。而socket.io会优先选择websocket作为数据交换的通道，所以推荐大家使用chrome来作为终端。

整体架构是这样的

<a href="http://www.f2es.com/wp-admin/www.f2es.com"><img title="termkit 架构" src="http://acko.net/files/termkit-9.png" alt="" width="500" height="352" data-markzhi="registered" /></a>

更多内容可以看作者写的文章：<a href="http://acko.net/blog/on-termkit">http://acko.net/blog/on-termkit</a> ]]></description>
            <pubDate>2011年11月09日</pubDate>
        </item>
                <item>
            <title>Firefox 7给web前端带来了什么</title>
            <link>http://www.w3ctech.com/p/657</link>
            <guid>http://www.w3ctech.com/p/657</guid>
            <category>行业快报</category>
            <description><![CDATA[ <h2>原文地址：<a href="http://hacks.mozilla.org/2011/09/whats-new-for-web-developers-in-firefox-7/">http://hacks.mozilla.org/2011/09/whats-new-for-web-developers-in-firefox-7/</a></h2>
<h2><strong>支持 text-overflow: ellipsis</strong></h2>
HTML:

<pre rel="HTML" class="prettyprint">&lt;html&gt;
&lt;body&gt;
      &lt;div&gt;I am some very long text!&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>

CSS:

<pre rel="CSS" class="prettyprint">div.inner {
    width: 120px;
    text-overflow: ellipsis;
    white-space:nowrap;
    overflow:hidden;
    color: red;
    border: 1px dashed #333;
    margin: 20px;
    padding: 10px;
}</pre>

Result:

<img class="alignnone" src="http://hacks.mozilla.org/wp-content/uploads/2011/09/ellipsis.png" alt="" width="161" height="75" data-markzhi="registered" />
<h2>WebSockets：协议更新并支持手机</h2>
默认情况下ff里的websocket是处于关闭状态的，现在已经默认启用了。

在手机的网络环境下存在高延迟和高链接损耗的问题，websocket可以给手机带来更好的体验。

ff7里的WebSocket协议做了次更新，已经是IETF上<a href="https://developer.mozilla.org/en/WebSockets">WebSockets</a>草案的最新版本了。

因为WebSocket依然是草案，所以依然保留了moz前缀。
<h2>更快的canvas</h2>
ff基于开发者的使用来对canvas进行了性能优化。看demo：<a href="https://developer.mozilla.org/en-US/demos/detail/runfield">https://developer.mozilla.org/en-US/demos/detail/runfield</a>
<h2>站点无法修改浏览器窗口</h2>
1.不能修改非window.open创建的窗口或标签页

2.不能修改含有多个标签页的窗口
<h2>支持新的<a title="Navigation Timing Spec" href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html">Navigation Timing spec</a></h2>
一个检测页面性能的工具，具体可以看 <a href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html">https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html</a> ]]></description>
            <pubDate>2011年10月18日</pubDate>
        </item>
                <item>
            <title>CSS选择器第4级介绍</title>
            <link>http://www.w3ctech.com/p/617</link>
            <guid>http://www.w3ctech.com/p/617</guid>
            <category>前端技术</category>
            <description><![CDATA[ <a href="http://w3ctech.com/b/wp-content/uploads/2011/10/css.png"><img src="http://w3ctech.com/b/wp-content/uploads/2011/10/css.png" alt="" title="css" width="500"  class="alignnone size-full wp-image-625" /></a>

最新的<a href="http://www.w3.org/TR/2011/WD-selectors4-20110929/#overview">CSS选择器4级工作草案</a>于2011年9月29日被发布。 新增了很多伪类。 总体来说，可以把新增的分为9类。 下面我们就逐类来研究一下。

<strong>1。复合选择</strong>
复合选择现在支持否定（Negation）和任何相匹配（Matches-any）的伪类选择。 复合选择，使我们能够通过组选择元素。

<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E:not(s1, s2)</td>
      <td>一个元素E既不匹配复合选择s1或配复合选择s2</td>
      <td>Negation 伪类</td>
    </tr>
    <tr>
      <td>E:matches(s1, s2)</td>
      <td>一个元素匹配复合选择s1和、或匹配复合选择s2</td>
      <td>Matches-any 伪类</td>
    </tr>
  </tbody>
</table>

在下面的例子。 前两个列表项将是红色的，其余的将是绿色的。

<pre rel="CSS" class="prettyprint">
&lt;style&gt;
li:not(.a, .b) {color:green;}
li:matches(.a, .b) {color:red;}
&lt;/style&gt;
</pre>
<pre rel="HTML" class="prettyprint">
&lt;ul&gt;
&lt;li class="a"&gt;hullo&lt;/li&gt;
&lt;li class="b"&gt;hullo&lt;/li&gt;
&lt;li&gt;hullo&lt;/li&gt;
&lt;li&gt;hullo&lt;/li&gt;
&lt;li&gt;hullo&lt;/li&gt;
&lt;/ul&gt;
</pre>

<strong>2。本地链接伪类</strong>
<code>:local-link</code>伪类 允许作者在网站上根据用户当前位置选择链接。 

<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E:local-link</td>
      <td>一个元素E作为连接的锚链接的源头，目标是当前文档</td>
      <td>本地链接伪类</td>
    </tr>
    <tr>
      <td>E:local-link(0)</td>
      <td>一个元素E作为连接的锚链接的源头，目标在当前文档域内</td>
      <td>本地链接伪类</td>
    </tr>
  </tbody>
</table>


如果网页的网址是 http://www.example.com/2011/03/, 链接1收到样式2。链接2会收到样式2和3。

<pre rel="CSS" class="prettyprint">
&lt;style&gt;
a:local-link {color:red;}
a:local-link(0) {font-family:Arial;}
a:local-link(1) {font-size:12px;}
&lt;/style&gt;
</pre>
<pre rel="HTML" class="prettyprint">
&lt;a href="http://www.example.com"&gt;Home&lt;/a&gt;
&lt;a href="http://www.example.com/2011"&gt;2011&lt;/a&gt;
</pre>


<strong>3。':nth-match()'伪类</strong>
The <code>:nth-match(an+b of selector-list)</code>伪类符号代表一个元素的an+b-1的兄弟姐妹匹配在它之前的文档树中的选择列表的任何零或正整数n值。
<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E:nth-match(n of selector)</td>
      <td>一个元素E,第n个兄弟姐妹匹配的选择</td>
      <td>结构伪类</td>
    </tr>
  </tbody>
</table>

下面的例子中，每一个奇数行的div都会是#ccc色。

<pre rel="CSS" class="prettyprint">
&lt;style&gt;
div:nth-match(2n+1) {background-color:#ccc;} /* represents every odd row of div */
div:nth-match(odd)  {background-color:#ccc;} /* same */
&lt;/style&gt;
</pre>

<strong>4。网格结构伪类</strong>
网格结构伪类是用于二维网格，如表。 以下模式：
<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E:column(selector)</td>
      <td>一个元素E代表了​​一个网格/表中属于代表的元素相匹配选择一列单元格</td>
      <td>网格结构伪类</td>
    </tr>
    <tr>
      <td>E:nth-column(n)</td>
      <td>一个元素E代表了​​一个网格/表中属于代表的元素相匹配选择第n列单元格</td>
      <td>网格结构伪类</td>
    </tr>
    <tr>
      <td>E:nth-last-column(n)</td>
      <td>一个元素E代表了​​一个网格/表中属于代表的元素相匹配选择第n列单元格, 从最后一个数起。</td>
      <td>网格结构伪类</td>
    </tr>
  </tbody>
</table>

下面的例子使C，E和G背景显示为黄色。

<pre rel="CSS" class="prettyprint">
&lt;style&gt;
:column(col.selected) { background: yellow; }
&lt;/style&gt;
</pre>
<pre rel="HTML" class="prettyprint">
&lt;table&gt;
  &lt;col span="2"&gt;&lt;/col&gt;
  &lt;col class="selected"&gt;
      &lt;tr&gt;
          &lt;td&gt;A &lt;/td&gt;
          &lt;td&gt;B &lt;/td&gt;
          &lt;td&gt;C
              &lt;tr&gt;
                  &lt;td span="2"&gt;D &lt;/td&gt;
                  &lt;td&gt;E
                      &lt;tr&gt;
                          &lt;td&gt;F &lt;/td&gt;
                          &lt;td span="2"&gt;G&lt;/td&gt;
                      &lt;/tr&gt;
                  &lt;/td&gt;
              &lt;/tr&gt;
          &lt;/td&gt;
      &lt;/tr&gt;
  &lt;/col&gt;
&lt;/table&gt;
</pre>

<strong>5。参考组合子</strong>
<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E /foo/ F</td>
      <td>一个元素F被一个元素E的属性foo编号参照</td>
      <td>参考组合子</td>
    </tr>
  </tbody>
</table>

下面的例子中input的编号被label的属性for参照

<pre rel="CSS" class="prettyprint">
&lt;style&gt;
label:matches(:hover, :focus) /for/ input, /* association by "for" attribute */
label:matches(:hover, :focus):not([for]) input { /* association by containment */
box-shadow: yellow 0 0 10px; }
&lt;/style&gt;
</pre>
<pre rel="HTML" class="prettyprint">
&lt;label for="phone"&gt;Phone Number&lt;/label&gt;
&lt;input type="input" name="phone_number" id="phone" /&gt;
</pre>


<strong>6。确定一个选择的对象</strong>
我们大家都熟悉的模式 <code>E > F</code> (CSS Selectors Level 2) 选择F元素为E元素的子元素. 也有办法反过来选。

<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$E > F</td>
      <td>一个元素E为F的父元素</td>
      <td>确定一个选择的对象</td>
    </tr>
  </tbody>
</table>

所以通过利用<code>$E > F</code>，我们可以选择<code>F</code>元素的父类<code>E</code>.
<pre rel="CSS" class="prettyprint">
&lt;style&gt;
$section #menu {border:1px solid red;}
&lt;/style&gt;
</pre>
<pre rel="HTML" class="prettyprint">
&lt;section&gt;
&lt;div id="menu"&gt;&lt;/div&gt;
&lt;/section&gt;
</pre>

<strong>7。时间维伪类</strong>
时间维（Time-dimensional）伪类是新推出的一组类用来通过当前显示时间点对元素进行分类，在时间维的canvas上，如在讲话时显示的HTML文档。
<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E:current</td>
      <td>一个元素E在目前的时间维canvas上</td>
      <td>时间维伪类</td>
    </tr>
    <tr>
      <td>E:current(s)</td>
      <td>一个元素E是:current元素最内层匹配s的</td>
      <td>时间维伪类</td>
    </tr>
    <tr>
      <td>E:past</td>
      <td>一个元素E目前在过去的时间维canvas上</td>
      <td>时间维伪类</td>
    </tr>
    <tr>
      <td>E:future</td>
      <td>一个元素E目前在未来的时间维canvas上</td>
      <td>时间维伪类</td>
    </tr>
  </tbody>
</table>

比如，以下规则会突出任何正在读的段落或列表项：

<pre rel="CSS" class="prettyprint">
&lt;style&gt;
:current(p, li, dt, dd) {
background: yellow;
}
&lt;/style&gt;
</pre>

<strong>8。不确定值（indeterminate-value）伪类 ':indeterminate'</strong>
The <code>:indeterminate</code> 伪类适用于其价值处于不确定状态的UI元素。 例如，<code>radio</code>和复选框元素可以在被选中和非选中状态之间切换， 但有时处于不确定状态, 既不被选中，也不取消选中. 同样，一个进度表，可以在一个不确定的状态完成时，是未知的。
如同<code>:checked</code>伪类， :indeterminate适用于所有的媒体。 例如， 一个<code>radio-group</code>的组件初始化时没有预先选定的选择, 即使在静态展示时，也会是 <code>:indeterminate</code>。
<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E:indeterminate</td>
      <td>用户界面元素E处于不确定的状态(既不选中，也不是没选中)</td>
      <td>indeterminate-value伪类</td>
    </tr>
  </tbody>
</table>
	
<strong>9. 属性选择: 区分大小写</strong>
属性选择可能包括标识符<code>i</code>近跟在右括号内(<code>]</code>). 当这个标志存在, 浏览器必须在ASCII范围内匹配属性值的大小写。
<table>
  <thead>
    <tr>
      <th>模式</th>
      <th>意思</th>
      <th>区域</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E[foo="bar" i]</td>
      <td>an E element whose foo attribute value is exactly equal to any (ASCII-range) case-permutation of bar</td>
      <td>属性选择: 区分大小写</td>
    </tr>
  </tbody>
</table>

下面是一个使用例子:
<pre rel="CSS" class="prettyprint">
&lt;style&gt;
[frame=hsides i] { border-style: solid none; }
&lt;/style&gt;
</pre>

<strong>结论</strong>
还有草案中的错误，辩论和不完整的信息，如果您想加入讨论，可以加入公开的邮件列表，在 <a href="http://lists.w3.org/Archives/Public/www-style/">www-style@w3.org</a>.
The latest spec is at: http://www.w3.org/TR/2011/WD-selectors4-20110929/#overview ]]></description>
            <pubDate>2011年10月10日</pubDate>
        </item>
                <item>
            <title>一些现阶段web标准没有解决的问题</title>
            <link>http://www.w3ctech.com/p/611</link>
            <guid>http://www.w3ctech.com/p/611</guid>
            <category>前端技术</category>
            <description><![CDATA[ <h2>原文：<a href="http://www.nczonline.net/blog/2011/10/03/when-web-standards-fail-us/" target="_blank">When web standards fail us</a></h2>
<h2>使用JavaScript读写cookie</h2>
document.cookie这个对象从一开始出现到现在都没有变化。这也意味着直到现在，我们想要操作cookie的时候，必须对cookie的字符串进行格式化。
<h2>JavaScript中的字符串格式化</h2>
在c和php里都有sprintf这个方法，printf 可能是许多程序员在开始学习C 语言时接触到的第二个函数（我猜第一个是main），但是可能很少会有人用到sprintf。

c里的sprint语法是这样的
<pre rel="C" class="prettyprint">int sprintf( char *buffer, const char *format [, argument] ... );</pre>
php里是这样的
<pre rel="PHP" class="prettyprint">sprintf(format,arg1,arg2,arg++)</pre>
sprintf的功能就是将格式化的字符串写入一个变量中。比如
<pre rel="PHP" class="prettyprint">&lt;?php
$number = 123;
$txt = &lt;code&gt;sprintf("With 2 decimals: %1\$.2f&lt;br /&gt;With no decimals: %1\$u",$number)&lt;/code&gt;;
echo $txt;
?&gt;</pre>
下一个版本的ECMAScript 会有一个类似的新方法<a href="http://wiki.ecmascript.org/doku.php?id=harmony:quasis&amp;s=functions" target="_blank">quasis</a>，但是这个方法的问题在于不能做到平稳退化，那么，或许一个简单的htmlEscape()就是一个很好的开始，或者直接实现一个String.format()方法。
<h2>JavaScript中日期对象的格式化</h2>
在js中存在一个date对象，我们最容易获取到的数据就是1970年到当前的毫秒数，但是问题在于平时我们肯定不会用这个来表达时间。当然date对象也提供单个方法来获取年月日小时，但是，我们真正需要的是一个我们能制定格式，然后浏览器能返回对应格式的时间的方法，比如'yy-mm--dd'或者'yy/mm/dd'。
<h2>增加一些常用的UI标签</h2>
最常用的有tab选项卡，轮播，展开收起的模块，树形菜单。我们所写的大部分UI相关的JavaScript代码都是在解决这几个问题。由于这些出现的实在是太频繁了，以致于足够让浏览器来考虑是不是将这些UI标签构造出来。
<h2><strong>JavaScript触摸事件</strong></h2>
触摸事件有一些，但是远不够，比如swipe, flick,tap, 和pinch就没有得到支持。
<h2>参考来源</h2>
<ul>
	<li><a title="sprintf，你知道多少？" href="http://blog.csdn.net/sjf331/article/details/339254">sprintf，你知道多少？</a></li>
	<li><a href="http://cn2.php.net/sprintf/">http://cn2.php.net/sprintf/</a></li>
</ul> ]]></description>
            <pubDate>2011年10月08日</pubDate>
        </item>
                <item>
            <title>（转）什么是重要的</title>
            <link>http://www.w3ctech.com/p/603</link>
            <guid>http://www.w3ctech.com/p/603</guid>
            <category>前端技术</category>
            <description><![CDATA[ 现在HTML5大行其道，预演预热的推广下，反倒会让人觉得有种不安感...现在浏览器正在承受不能承受之重..

话不多说，转一篇<a href="http://lifesinger.wordpress.com/" target="_blank">玉伯</a>在2010年9月6号在自己博客上发的文章，其中意味，自去体会。

----------------------------------------------------------------------------------------------------------------------------------------------

HTML5 很火，忍不住也阅读了一遍 HTML5 spec, 发现除了对记忆力是个考验之外，增加的内容很少：

首先是 markup, 增加了 header, footer, section, nav 等元素，本质上和 div + class 无啥区别，考验的是记忆力和小学语文的功底。

其次增加了一堆 new APIs: Canvas/Web Storage/Drag-and-drop/Web SQL Database/Geolocation/Web Socket/Server-Sent Event 等等，这些内容的使用并无什么技术难点，翻翻规范手册，都是半天就能“精通”的。

追寻这些新技术，很容易让人有种走在技术前沿很牛逼的虚荣感。但实际上，会用 header/footer, 并不代表你就懂得了语义。就如多学了几个成语，并不意味着你的作文水平就有提高。
Geolocation 等 API, 也是如此。淘宝 UED 有几位设计达人，用的是 Photoshop 7.0. 倒是我这种半桶水，会紧跟潮流，装个英文原版的 CS4. 比喻不是很贴切，但从技能的深度上讲，有去学 Web SQL Database 的精力，不如去温习遍数据库基础教程。玩 Canvas 前，不如先去学学计算机图形学。否则永远是蜻蜓点水，以为走在前沿，其实只是凑个热闹，迟早成为舞台下的观众。

关注是可以的。有时间（我觉得大部分人其实都没时间），去尝尝鲜也是有益的。但是对于大部分营养不良的前端，推荐还是脚踏实地老老实实的去学一门传统编程语言，去把数据结构/基础算法/设计模式/数据库等等基础知识点给搞瓷实了再说。这样，等 HTML9 出来的时候，对你而言，无非就是淘汰了一些旧 API, 增加了一些新 API 而已。

对于武林高手，内功最重要。招式套路，只能街头赚个掌声。

对于程序员，真正的核心竞争力是基本功。

永远不要舍本逐末，否则你学的新东西越多，被淘汰的可能性反而越大。 ]]></description>
            <pubDate>2011年09月21日</pubDate>
        </item>
                <item>
            <title>（译）使用setimmediate实现可伸缩执行的脚本</title>
            <link>http://www.w3ctech.com/p/597</link>
            <guid>http://www.w3ctech.com/p/597</guid>
            <category>JavaScript</category>
            <description><![CDATA[ 原文地址：<a href="http://www.nczonline.net/blog/2011/09/19/script-yielding-with-setimmediate/" target="_blank">http://www.nczonline.net/blog/2011/09/19/script-yielding-with-setimmediate/</a>

看过我对JavaScript 性能优化相关的讨论的同学们一定很了解我的一个癖好，就是<a href="http://www.nczonline.net/blog/2009/08/11/timed-array-processing-in-javascript/" target="_blank">将一大段的script分解成多个块</a>来执行。通过使用setTimeout()，你可以去改变特定代码执行的时间，从而做到让UI现场执行已经在队列里的任务。比如，你可以通过这样的方式把要执行的代码在50ms后加到UI线程队列里：
<pre rel="JavaScript" class="prettyprint">setTimeout(function(){
   //do  something
}, 50)</pre>
那么，在50ms后，这个函数就会被添加到队列里，并在轮到它的时候执行。调用setTimeout()方法可以允许当前的JavaScript任务完成从而下一个UI更新可以顺利进行。

虽然我一直很支持使用setTimeout()来提高性能，但是还是存在几个问题。第一个并且是最重要的问题是不同的浏览器有着不一样的时间精确度。IE8和更早的IE的时间精确度是15.6ms，而IE9，或者更新的浏览器，还有chrome的时间精确度已经到达4ms。所有的浏览器都强制给setTimeout设置了一个最低延迟值，所以setTimeout(fn, 0)实际上在大于0ms的时间之后才会执行，具体取决于对应的时间精确度。

另一个是电源使用的问题。管理时间关系到笔记本或者手机的电池使用。Chrome曾经尝试把时间精确度降低到1ms，结果发现会增加笔记本电池的损耗。最后还是觉得把时间精确度设置回4ms。其他浏览器也做过类似的尝试，不过许多油门计时器分辨率为1s。微软发现时间精确度为1ms的时候，电池的使用时间会降低25%。实际上，IE9会判断笔记本是否在使用电池的情况下运行，如果是电池，则时间精确度为15.6ms，如果是直接插的电源则时间精确度会降低到4ms。

来自W3C Web Performance Working Group的一个方案“ <a href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html">Efficient Script Yielding</a> ”，定义了一个新的函数去实现脚本的分块执行的setImmediate()方法。 这个方法接收一个函数作为参数，它可以让这个函数在UI线程空闲的时候执行。基本的用法：
<pre rel="JavaScript" class="prettyprint">var id = setImmediate(function(){
    //do something
});</pre>
setImmediate()函数会返回一个id，这个id可以通过clearImmediate()方法来取消这个过程。

我们也可以给它传递一些参数
<pre rel="JavaScript" class="prettyprint">setImmediate(function(doc, win){
    //do something
}, document, window);</pre>
用这个方式来传递可选的参数意味着你不需要总是使用一个闭包来让函数包含一些有用的信息。

setImmediate()可以让浏览器不需要去管理进程的定时器。不需要去等待更耗电的系统中断，浏览器只需要等待UI队列空闲，然后把新的JavaScript任务插入进去。Node.js的开发者会比较容易理解这个问题，因为process.nextTick()在自己的环境里做了相同的事情。

现在只有ie10支持这个方法，而且因为还没有完全定下来，所以使用了msSetIntermediate()。IE10的Test Drive上也有一个setImmediate()的例子，展示了新方法带来的性能提升。这个例子使用一个延迟来排列一些数据，排序之后的状态会直接展示出来。 ]]></description>
            <pubDate>2011年09月20日</pubDate>
        </item>
                <item>
            <title>Page Speed支持Chrome及且提供web版</title>
            <link>http://www.w3ctech.com/p/590</link>
            <guid>http://www.w3ctech.com/p/590</guid>
            <category>行业快报</category>
            <description><![CDATA[ Page Speed，你有听过吗？
Page Speed是google提供的一款与性能优化相关的浏览器插件，最初只能在火狐浏览器上运行，基于火狐浏览器的firebug。
最近Page Speed已经开发出支持Chrome的插件，如果你有兴趣在Chrome上使用Page Speed，可以移步去page speed的官方网站下载这个插件：<a href="http://code.google.com/intl/zh-CN/speed/page-speed/docs/using_chrome.html" title="Using Page Speed for Google Chrome" target="_blank">Using Page Speed for Google Chrome</a>。

<strong>不仅如此，Page Speed在次向大家提供了web线上版</strong>，web版支持桌面版和移动版的性能分析，并且生成详细的报名，由于目前还是实验室产品，还不够完善，不过这算是一个挺有意思的消息，如果你有兴趣可以移步去看看：<a href="http://pagespeed.googlelabs.com/" title="Page Speed Online  " target="_blank">Page Speed Online</a>（如果不能打开，请使用<a href="https://developers.google.com/pagespeed/" title="最新网址" target="_blank">最新网址</a>）。
<a href="http://w3ctech.com/b/wp-content/uploads/2011/09/pagespeed.jpg"><img src="http://w3ctech.com/b/wp-content/uploads/2011/09/pagespeed-300x126.jpg" alt="Page Speed Online" title="Page Speed Online " width="300" height="126" class="alignleft size-medium wp-image-591" /></a> ]]></description>
            <pubDate>2011年09月16日</pubDate>
        </item>
                <item>
            <title>IE10预览版随着Windows 8开发者预览版发布</title>
            <link>http://www.w3ctech.com/p/576</link>
            <guid>http://www.w3ctech.com/p/576</guid>
            <category>行业快报</category>
            <description><![CDATA[ 相信今天已经有很多同学都下载了Windows 8的开发者预览版，抢先体验了一把Win8，那么对于前端来说，IE10 pre带来了一些什么呢？

<a href="http://w3ctech.com/b/wp-content/uploads/2011/09/1.png"><img class="alignnone size-full wp-image-578" title="1" src="http://w3ctech.com/b/wp-content/uploads/2011/09/1.png" alt="" width="500" data-markzhi="registered" /></a>

微软在发布Win8的同时，也在MSDN上发了一篇文章，叫做《<a href="http://msdn.microsoft.com/en-us/ie/gg192966" target="_blank">Internet Explorer 10 Guide for Developers</a>》，IE10开发者指南。这里会主要罗列下IE10带来的一些新变化，部分做了一点说明。

有几点要注意的：

微软还未在Win7上发布IE10 pre，所以要体验IE10的同志必须得搞个Win8，同时微软也承诺回来未来某个时间发布Win7平台的IE10 pre，拭目以待吧。
<p align="left">除了阅读这个指南之外，你一定也要去看下<a href="http://go.microsoft.com/fwlink/?LinkID=190919">发布说明</a>，去了解一些安装信息和问题，还有去IE Test Drive网站查看新的demo和实例。你可以访问<a href="http://go.microsoft.com/fwlink/?LinkID=58649">Internet Explorer Developer Cente</a> 和 <a href="http://go.microsoft.com/fwlink/?LinkId=214816">MSDN</a> 来了解更多详细的针对开发者的技术信息。</p>

<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSS">Cascading Style Sheets (CSS)</a>
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSAdvancedLayout">Advanced Layout</a>（更高级的布局）
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSConnected">CSS Regions</a>（基于区域的布局，可以看<a href="http://www.qianduan.net/css-regions.html">http://www.qianduan.net/css-regions.html</a>）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSMultiCol">CSS3 Multi-column Layout</a>（多列布局）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSFlexBox">Flexible Box (“Flexbox”) Layout</a> （在 CSS2 的基础上，我们将能更灵活地调整页面上各个容器的大小和位置 <a href="http://blog.imbolo.com/the-css3-flexible-box-model/">http://blog.imbolo.com/the-css3-flexible-box-model/</a>）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSGrid">Grid Alignment</a>（基于网格的对齐）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSFloats">Positioned floats</a>（定位浮动）</li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSS3DTransforms">CSS3 3-D Transforms</a> （3D的css3 transforms支持）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSAnimations">CSS3 Animations</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSGradients">CSS3 Gradients</a> （渐变）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSTransitions">CSS3 Transitions</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSText">CSS3 Text</a>
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSTextShadow">The <strong>text-shadow</strong> property</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSHyphenation">Hyphenation</a> （截断文字）</li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSPanZoom">Panning and Zooming</a> （针对触摸和手势的处理）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272902.aspx#_CSSRemoveLimits">Removal of style sheet limits</a> （之前版本的IE最多只能引入31个样式表，现在不做限制了）</li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272903.aspx#_DOM">Document Object Model (DOM) support</a>
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272903.aspx#_DOMHitTesting">Advanced Hit Testing APIs</a> （判断元素重合）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272903.aspx#_DOMFP">CSSOM Floating Point Value support</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272903.aspx#_DOMMediaQuery">Media Query Listeners</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272903.aspx#_DOMTouch">Pointer and Gesture DOM events</a></li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272904.aspx#_ECMAScript5">ECMAScript 5 (ES5) support</a>
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272904.aspx#_ECMAScript5Strict">The strict variant of ECMAScript (“ES5 strict mode”)</a> （依照ECMAScript增加严格模式）</li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh440435.aspx#_F12DevTools">F12 Developer Tools (Not available in Metro style apps.)</a>
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh440435.aspx#_DevToolsWebWorker">Improved support for workers</a></li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5">HTML5 support</a>
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5Async">Asynchronous Script Execution</a> （脚本的异步执行）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5AppCache">Application Cache ("AppCache")</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5DragDrop">Drag and Drop</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5FileAPI">File API</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5FormsVal">Forms Validation</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5Range">Progress and Range Control</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5History">History</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5Parsing">Parsing</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5Sandbox">Sandbox</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5WebWorker">Web Workers</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5ChannelMessaging">Channel Messaging</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5WebSockets">Web Sockets</a> （我喜欢这个）</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272905.aspx#_HTML5Spellcheck">Spellcheck</a> （拼写检查）</li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh440436.aspx#_IndexedDB">Indexed Database API ("IndexedDB")</a></li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh440437.aspx#_SVG">SVG</a>
<ul>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh440437.aspx#_SvgFilters">SVG Filter Effects</a></li>
</ul>
</li>
	<li><a href="http://msdn.microsoft.com/en-us/ie/hh272906.aspx#_Perf">Web performance APIs</a>（参考<a href="http://www.w3.org/2010/webperf/">http://www.w3.org/2010/webperf/</a> 设计的性能监控API）</li>
</ul>
<div>更详细的内容，大家可以去<a href="http://msdn.microsoft.com/en-us/ie/gg192966">http://msdn.microsoft.com/en-us/ie/gg192966</a>仔细阅读下</div> ]]></description>
            <pubDate>2011年09月15日</pubDate>
        </item>
                <item>
            <title>阿里云手机云App内部开发大赛</title>
            <link>http://www.w3ctech.com/p/545</link>
            <guid>http://www.w3ctech.com/p/545</guid>
            <category>行业快报</category>
            <description><![CDATA[ 2011年9月6号晚，淘宝的懒懒交流会举办了一场特别的会议，阿里云手机云App内部开发大赛交流会。

会上，我们见到了阿里云手机真机，黄色，粉色和黑色外壳三款。其用户界面由两部分组成：

1、固定的前三屏，其中前两屏为阿里云云App开发的功能区，第三屏为android系统的原生界面，包括了各种设置等应用

2、后三屏，为用户从阿里云App Store添加到桌面的应用。需要指出的是，这三屏其实就是三个应用的运行界面，与android或ios设备中的添加应用体验完全不同，这意味着用户只能在阿里云手机上添加三个来自阿里云App Store的应用。至少目前的版本上是如此。

阿里云App的执行环境是Webkit+V8,Webkit的版本大概相当于Chrome5或8的阶段，从步天同学在会上介绍的特性来看，多数CSS3的特性还是支持的。另外，本地数据库WebSql也是支持的。

虽然在使用过一段时间后你可能会对它的一些细节感到郁闷，不过这总算是阿里云手机的第一版，期待其未来能够在更多细节上多下功夫。 ]]></description>
            <pubDate>2011年09月07日</pubDate>
        </item>
                <item>
            <title>根据HTML规范规定，可选择不闭合的标签</title>
            <link>http://www.w3ctech.com/p/429</link>
            <guid>http://www.w3ctech.com/p/429</guid>
            <category>前端技术</category>
            <description><![CDATA[ 如果你从一开始接触的就是xhtml的规范的话，那你应该知道，xhtml有一条很严格的规定，就是所有标签必须闭合，包括img：

&lt;img src=“url” alt=“alt” /&gt;

但是在HTML规范(即doctype声明为html4.01 strict或html5)中，有部分标签是可以不用闭合的：

&lt;html&gt;
&lt;body&gt;
&lt;colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;tbody&gt;
&lt;td&gt;
&lt;p&gt;
&lt;dt&gt;
&lt;dd&gt;
&lt;li&gt;
&lt;option&gt;
&lt;tfoot&gt; （html5下是标准的）

如果你对此非常有兴趣，可以移步去W3C官方网站查看：
1、HTML4标签的规定：<a title="http://www.w3.org/TR/html4/index/elements.html" href="http://www.w3.org/TR/html4/index/elements.html" target="_blank">http://www.w3.org/TR/html4/index/elements.html</a>
2、HTML5标签的规定：<a title="http://dev.w3.org/html5/spec/syntax.html#optional-tags" href="http://dev.w3.org/html5/spec/syntax.html#optional-tags" target="_blank">http://dev.w3.org/html5/spec/syntax.html#optional-tags</a>
<a title="http://www.w3.org/TR/html5/syntax.html#optional-tags" href="http://www.w3.org/TR/html5/syntax.html#optional-tags" target="_blank"> http://www.w3.org/TR/html5/syntax.html#optional-tags</a>

克军也发表了相关文章：<a href="http://hikejun.com/blog/?p=525">http://hikejun.com/blog/?p=525</a> ]]></description>
            <pubDate>2011年09月05日</pubDate>
        </item>
                <item>
            <title>前端代码库JSLab新版发布</title>
            <link>http://www.w3ctech.com/p/400</link>
            <guid>http://www.w3ctech.com/p/400</guid>
            <category>行业快报</category>
            <description><![CDATA[ <strong><a href="http://www.jslab.org.cn" target="_blank">前端代码库JSLab</a></strong>(它是一个免费的HTML, JavaScript和CSS代码库，其中的代码内容由前端同学贡献)，于近日发布了其第3版。

此次更新主要包括：

1. 全新的用户操作界面
<img class="alignnone size-full wp-image-412" title="jslab" src="http://w3ctech.com/b/wp-content/uploads/2011/09/jslab1.jpg" alt="" width="500"  />

2. 更平滑，流畅的交互体验
<a href="http://www.jslab.org.cn/?tag=Book"><img class="alignnone size-full wp-image-413" title="jslab" src="http://w3ctech.com/b/wp-content/uploads/2011/09/jslab2.jpg" alt="" width="500"  />
</a>
<img class="alignnone size-full wp-image-414" title="jslab" src="http://w3ctech.com/b/wp-content/uploads/2011/09/jslab3.jpg" alt="" width="500"  />
3. 加入离线应用支持
4. 加入本地数据库支持
5. 本地数据库及线上数据同步服务
6. 代码分享
<img class="alignnone size-full wp-image-415" title="jslab" src="http://w3ctech.com/b/wp-content/uploads/2011/09/jslab4.jpg" alt="" width="500"  />

如果您使用IOS设备，您会发现，JSLab是一个很好的WEB APP，您可以在iPhone, iPad上获得很酷的操作体验。
<a href="http://www.jslab.org.cn/"><img class="alignnone size-full wp-image-416" title="jslab" src="http://w3ctech.com/b/wp-content/uploads/2011/09/jslab5.png" alt="" width="500" /></a>

还等什么，现在就去体验：<a href="http://www.jslab.org.cn" target="_blank">http://www.jslab.org.cn</a>，欢迎同学们贡献代码！ ]]></description>
            <pubDate>2011年09月04日</pubDate>
        </item>
                <item>
            <title>百度正式加入W3C</title>
            <link>http://www.w3ctech.com/p/287</link>
            <guid>http://www.w3ctech.com/p/287</guid>
            <category>行业快报</category>
            <description><![CDATA[ 继中国联通以Full Member的身份加入W3C以后，作为中国排名前几位的互联网公司百度(baidu.com)也在本月正式以Full Member的身份加入W3C。

信息来源于W3C中国新浪微博：W3C中国在2011年9月2日在新浪微博上宣布:"欢迎中国大陆第二家Full Member -- 百度加入W3C！"。

<img src="http://w3ctech.com/b/wp-content/uploads/2011/09/w3c-baidu.jpg" alt="百度加入W3C" title="百度加入W3C" width="500"  class="alignnone size-full wp-image-423" />

关于本信息的url为：http://weibo.com/1893751011/xmjdKl04x?type=repost ]]></description>
            <pubDate>2011年09月03日</pubDate>
        </item>
                <item>
            <title>CSS(层叠样式表)中的@import</title>
            <link>http://www.w3ctech.com/p/268</link>
            <guid>http://www.w3ctech.com/p/268</guid>
            <category>前端技术</category>
            <description><![CDATA[ @import可以理解为向文档（HTML）导入样式（CSS），他的使用方法有以下几种：

1、在HTML中的head中：
<pre rel="CSS" class="prettyprint">
&lt;style type="text/css"&gt;
@import url("/css/style.css");
&lt;/style&gt;
</pre>

2、在CSS（style.css）文件中：

//导入规则需要放在样式表的最前面
<pre rel="CSS" class="prettyprint">
@import url("/css/layout.css");
</pre>
//书写CSS文件中的其他样式，以下样式会覆盖layout.css的样式。

通过link的方式引入sytle.css，这样可以降低(X)HTML文档的复杂性，并且允许在一个位置管理所有的样式表。导入规则需要放在样式表的最前面，否则它们可能工作不正常。记住，书写在导入样式表下方的样式，是会覆盖被导入的样式表中的样式的。

尽管从理念上说可以将样式表导入到本身也被导入的样式表中（比如在layout.css中在使用@import导入其他样式文件），但是对这种链式结构或者多层嵌套的支持不完善。因此，应该避免两层以上的嵌套导入。

Windows的IE 5/6有一种奇怪的特性，它会影响只使用导入规则的页面。当装载受影响的页面时，在最终显示样式之前，页面会暂时以无样式的形式显示。这个bug称为“Flash of Unstyled Content”（简称为FOUC）bug。在文档头中放一个link或script元素可以避免这个bug，所以为了更好的解决这个问题，需要链接基本的样式表，然后在从那里导入样式。

<strong>当我们知道究竟怎么回事以后，以后我们就可以正确的去使用@import，而不像以前所说的那样，不使用@import，因为IE6有bug。</strong> ]]></description>
            <pubDate>2011年09月03日</pubDate>
        </item>
                <item>
            <title>JavaScript 类型检测方法</title>
            <link>http://www.w3ctech.com/p/266</link>
            <guid>http://www.w3ctech.com/p/266</guid>
            <category>前端技术</category>
            <description><![CDATA[ 在JavaScript中要检测一个变量是不是基本类型？typeof操作符是最佳的工具。更具体的说，typeof是确定一个变量是字符串、数值、布尔值、还是undefined的最佳工具。如果变量的值是一个对象或null，则typeof操作会像下面例子中所示的那样返回“object”:
<pre rel="JavaScript" class="prettyprint">
var s = "w3ctech";
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
alert(typeof s); //string
alert(typeof i); //number
alert(typeof b); //boolean
alert(typeof u); //undefined
alert(typeof n); //object
alert(typeof o); //object
</pre>
虽然在检测基本数据类型时typeof是非常得力的助手，但是在检测引用类型的值时， 这个操作符的用处不大。通常，我们并不是想知道某个值是对象，而是想知道它是什么类型的对象。为此，ECMAScript提供了instanceof操作符，其语法如下：
<pre rel="JavaScript" class="prettyprint">
result = variable instanceof constructor
</pre>
如果变量是给定引用类型（由构造函数表示）的实例，那么instanceof操作符就会返回true。请看下面的例子：
<pre rel="JavaScript" class="prettyprint">
alert(person instanceof Object); //变量person 是 Object吗？
alert(colors instanceof Array); //变量colors 是 Array吗？
alert(pattern instanceof RegExp); //变量pattern 是 RegExp吗？
</pre>
根据规定，所有引用类型的值都是Object的实例。因此，在检测一个引用类型值和Object构造函数时，instanceof操作符始终会返回true。当然如果使用instanceof操作符检测基本类型的值，则始终会返回false。因此基本类型不是对象。

注意：使用typeof操作符检测函数时，该操作符会返回“function”。在Safari和Chrome中使用typeof检测正则表达式时，这个操作符会错误地也返回“function”。

safari 和 chrome中,这个bug产生的原因是, 正则对象实现了调用接口,即内部的[[Call]]方法. 譬如/\d/('123');早期的firefox也存在这个bug.后来被修复了.safari,chrome的 typeof运算符调用的内部方法的逻辑,就是简单的看这个对象是不是实现了[[Call]]接口.实现了,就认为是一个函数对象. 其实对于safari,还有一些host object.也存在此类问题.譬如某些和DOM相关的东西.就不一一列举了.

补充:

instanceof 运算符的本意不是类型检查,而是检测.instanceof 左边的运算元,是否是右边运算元的一个实例.所以变相的提供了一种类型检查的能力.但这个是不可靠的. 比如 arr instanceof Array. 如果 arr是其他窗体内创建的数组.这个检测就会失败. 因为它是另外窗体的Global.Array的实例.而不是当前窗体的. 

还有一种极端情况:
<pre rel="JavaScript" class="prettyprint">
var arr = [];
arr.__proto__ = {};
arr instanceof Array;//false
</pre>
所以才有借助ECMAScript object内部属性[[Class]]的需求.即{}.toString.call(arr)的出现.

那么还有没有其他办法呢？ 答案是yes. 参考下面的代码:
<pre rel="JavaScript" class="prettyprint">
var arr =[];
arr.constructor && arr.constructor == Array.toString();// true. 
</pre>
原理是通过比较对象构造器的字符串表示.当然,严格来说.这些信息都是可以后期伪造或更改的. 所以还是{}.toString.call是最靠谱的做法.


但,你应该了解,从性能角度来说. typeof的性能是最佳的. 而 constructor 和{}.toString.call 在IE系则是constructor的性能要比后者高那么一丁点.而在非IE.后者的效率要比constructor方式性能高10倍左右. 所以最佳实践不用说了,只要不是 object.建议使用typeof.否则用{}.toString.call. ]]></description>
            <pubDate>2011年09月03日</pubDate>
        </item>
                <item>
            <title>雅虎Web开发工具将逐步放弃支持IE 6</title>
            <link>http://www.w3ctech.com/p/289</link>
            <guid>http://www.w3ctech.com/p/289</guid>
            <category>行业快报</category>
            <description><![CDATA[ 据国外媒体报道，雅虎加入微软、谷歌和许多开发开发商的行列，逐步放弃支持IE 6的网站，减少雅虎Web编程工具对2001年推出的IE 6浏览器的支持。
雅虎上周宣布其雅虎用户接口（YUI）工具将减少对IE的支持。雅虎用户接口工具是一个开源软件项目，向Web开发人员提供他们能够用于构建高级网站的代码模块。雅虎自然也是这个工具的用户。
IE 6是在2001年推出的，缺少对于许多Web标准的支持，包括老的标准和许多新标准。IE 5处理基于Web的JavaScript程序的能力较弱。这种程序对于动态的丰富的网站时代是非常重要的。IE 6还容易受到更多的安全威胁。虽然IE 6的使用正在逐步减少，但是，它的应用仍然是很普遍的，特别是因为IE 6是内置在Windows XP操作系统中并且很难从企业环境中移出去。
雅虎用户接口开发人员Eric Miraglia和Matt Sweeney在博客中说，雅虎预计在2011年把对IE 6的支持从A级降到C级，因此雅虎有更多的时间把重点放在移动浏览器和其它重要的新领域。
雅虎称，我们在下一个GBS（分级浏览器支持）更新中将把IE 6的技术支持级别从A级降到C级。通过把IE 6的支持降到C级，我们在保证为这些用户提供一致的基本体验，同时将释放更多的资源为使用现代的、能力更强的浏览器的数百万用户提供更丰富的体验。
转载至http://cnbeta.com/articles/126666.htm，做相应修正。 ]]></description>
            <pubDate>2011年07月03日</pubDate>
        </item>
                <item>
            <title>W3C中国成立深圳办事处</title>
            <link>http://www.w3ctech.com/p/186</link>
            <guid>http://www.w3ctech.com/p/186</guid>
            <category>行业快报</category>
            <description><![CDATA[ 2011年3月21日 – W3C中国继北京办事处之后，W3C中国在深圳市高新技术开发区虚拟大学园内的北京航空航天大学深圳研究院设立国内第二家分支机构——W3C深圳办事处。
W3C中国区总部寄望W3C深圳办事处全力打造国际化南方发展基地，瞄准最新国际Web标准和战略性新兴产业重点发展方向，特别是W3C在移动互联网、网络安全、无障碍化网络、以及Web & TV等方面的技术优势、立足珠三角地区ICT国际领先标准和科技成果推广，促进珠三角地区高新技术企业和科研机构与国内外Web标准领域之间的信息沟通与互动，加强与深圳地区和全球、全国ICT行业标准方面的合作，以新技术新标准服务高新技术企业，为珠三角地区的企业、高校、及科研机构参与国际信息技术标准化的研究、集成和推广提供更好的服务，与深圳市共同为本土企业和科研机构参与国际合作与竞争开启新合作的新篇章。 ]]></description>
            <pubDate>2011年03月21日</pubDate>
        </item>
                <item>
            <title>HTML5中文兴趣小组</title>
            <link>http://www.w3ctech.com/p/104</link>
            <guid>http://www.w3ctech.com/p/104</guid>
            <category>行业快报</category>
            <description><![CDATA[ <h3>什么是W3C</h3>
<p>
马路需要交警，网路也一样。Tim Bernes Lee在网络上有两贡献，一是发明互联网，二是成立W3C。W3C就是互联网的交警。今天HTML在不同浏览器上通用，其他前端网络技术可以跨浏览器使用，都是W3C在推动及促使这些技术的形成。当然W3C本身不去实践那些技术，这个责任由浏览器承担，W3C只是负责写规范，浏览器商，运营商，手机制造商把规范变成可以使用的东西。今天W3C负责的规范很多，包括了HTML5。
</p>
<h3>W3C有谁？</h3>
<p>
交警之所以可以指挥交通，因为政府人民付诸它这个权利。那又是谁付诸W3C这个权利？其实我也不知道，可能也就是历史因素。网络是由美国国防发明，互联网则是Tim Bernes Lee在欧洲发明。当时欧洲和美国都支持W3C，就这样慢慢演变成为一个代表性团体（想到联合国，联合国也是二战战胜国成立然后慢慢的就演变成为一个世界组织）
</p>
<p>
W3C要吃饭。W3C有300余成员，每一个成员公司按照不同的国家，利润和性质交不同的成员费。按照2007年的会费，一家印度盈利小公司可能付953美金，一家美国非盈利公司缴付6350美金而一家大型法国盈利公司或许就需要缴付65,000欧元。详情看<a href="http://www.w3.org/Consortium/fees">W3C收費</a>。
</p>
<p>
W3C成员其中包括了各浏览器商Microsoft，Google，Firefox，Opera，Apple。
</p>
<h3>小组由来</h3>
<p>
W3C有70多个小组，HTML5工作小组或许是大家最熟悉的。这个小组制定你和我将来会如何写html代码。html5中文小组让html5有我们的声音。
</p>
<p>
html5中文兴趣小组的想法要谈到今年在台北举办的<a href="http://coscup.org/2010/zh-tw">COSCUP／FOSS.ASIA</a>。在八月的聚会，我有幸认识到来自<a href="http://pingyeh.blogspot.com/">Google的Pingooo老师</a>，<a href="http://www.w3.org/People/all#kennyluck">W3C的Kenny lu兄</a>，<a href="http://blog.bobchao.net/">活跃在火狐台湾社区的柏強兄</a>。我们大家都觉得html5小组应该有一个中文通道。择日不如撞日，当时我们就拉来了<a href="http://people.w3.org/mike/">W3C的联络人Mike Smith</a>，和<a href="http://my.opera.com/chaals/blog/">Opera的标准官Chaals</a>。当场游说他们。Mike非常赞成，提出了按照程序只要两个(三个？)W3C成员公司支持小组成立就可以了。Chaals本来就是在W3C的Opera代表，立马就说Opera支持。
</p>
<p>
那时是八月，九月我应Google中国的邀请，出席了<a href="http://www.google.com/intl/zh-CN/events/devfests/2010/">北京的Google DevFest</a>。当时我和大陆的朋友分享了这个idea。W3C中国的安琪，<a href="http://www.twinsenliang.net/">纹身佬彪叔</a>，<a href="http://www.w3ctech.com/">W3Ctech的裕波兄</a>都说一定要有HTML5中文小组。就这样 我们大家就开了邮件小组，Kenny正式向W3C申请创办小组。就这样我们就开始了成立W3C HTML5 中文兴趣小组的路程。
</p>
<h3>这小组到底做什么？</h3>
<p>
<a href="http://www.w3.org/Consortium/activities">W3C的70多个小组</a>可以归类为工作小组working group，兴趣小组interest group，孵化小组incubator group，协调小组coordination group。中文小组归类为兴趣小组主要让对课题有兴趣的人交流，
</p>
<blockquote><p>Interest Groups</p>
<p>
The primary goal of an Interest Group is to bring together people who wish to evaluate potential Web technologies and policies. An Interest Group is a forum for the exchange of ideas.
</p>
</blockquote>
<p>
<a href="http://pingyeh.blogspot.com/2010/08/w3c-chinese-html-interest-group.html">Pingooo在他的博客</a>提到一些我们可以关注的课题，比如：
</p>
<ul>
<li>直排文書的 CSS3 規格和實作</li>
<li>Ruby 的 HTML(5) 規格和實作，Ruby 就是像國小課本文字旁的注音符號那樣縮小排到本文旁邊的字。</li>
<li>Web font 的中文支援</li>
</ul>
<p>
除此之外，其他非HTML5小组也需要和我们互动，像我们也需要和他们互动。比方十月奥斯陆的小聚会我和编写W3C DAP calendar contacts API的<a href="http://richt.me/">Richard Tibbett </a>聊到，他也说希望可以找我们讨论在calendar API的农历做支持。同时大家觉得W3C无论哪个小组文档或规范需要听见我们的看法，不要迟疑。
</p>
<p>
 还有顺便提到，帮忙申请此Kenny lu兄也将担任Ruby的编辑。
</p>
<h3>谁可以参与？</h3>
<p>
这个小组是开放制度，无论你的公司是W3C成员否，你都可以参与。看如何参与。这个小组不属于任何“专家”，大家都都是专家，大家都是学生。
</p>
<h3>如何参与？</h3>
<p>
我们非常欢迎大家参与。你可以
</p>
<ol>
<li>讨论HTML，甚至是其他技术的问题。包括CSS，SVG等。</li>
<li>订阅<a href="http://lists.w3.org/Archives/Public/public-html-ig-zh/">HTML5中文邮件群组</a>。</li>
<li>修改<a href="http://public-html-ig-zh.wikidot.com/start">HTML5中文维基</a> （暂时性，我们迟些应该决定是否要搬到W3C那）</li>
<li>HTML5中文小组宪章： <a href="http://www.w3.org/html/ig/zh/charter.html">英文</a>，<a href="http://www.w3.org/html/ig/zh/charter.zh.html">简中</a>，<a href="http://www.w3.org/html/ig/zh/charter.zh-hant.html">繁中版</a>。</li>
<li>也是最关键的。就是我们需要人手整理我们所讨论的成果。比方早前讨论的直排非常有用，需要有人整理出来。（有兴趣帮忙者可联络我）。</li>
</ol>
<h3>如何订阅？</h3>
<p>
柏强在维基有解释到
</p>
<ol>
<li>寄封信到 public-html-ig-zh-requestATw3.org </li>
<li>內文可留白</li>
<li>Subject / 信件標題打上「subscribe」</li>
<li>接著會收到確認信，回個信什麼都不必打就可以了</li>
<li>在你發第一封信到 public-html-ig-zh 時，你需要另外到 W3C 網站上選擇是否願意讓自己的信件保留一份在主機上。</li>
<li>如果一直遲遲等不到自己的信件出現，別擔心，柏強也等了五六個小時 orz。</li>
</ol>
<h3>总结</h3>
<p>邮件群组见！</p>

此信息转自子斌的blog：<a href="http://zibin.me/2010/11/html5%E4%B8%AD%E6%96%87%E5%85%B4%E8%B6%A3%E5%B0%8F%E7%BB%84/">html5中文兴趣小组</a> ]]></description>
            <pubDate>2010年11月29日</pubDate>
        </item>
                <item>
            <title>HTML5中文兴趣小组成立，欢迎订阅</title>
            <link>http://www.w3ctech.com/p/63</link>
            <guid>http://www.w3ctech.com/p/63</guid>
            <category>行业快报</category>
            <description><![CDATA[ 通过子斌与kenny的大力推动，W3C批准同意成立HTML中文兴趣小组，欢迎各位订阅。

群组：http://lists.w3.org/Archives/Public/public-html-ig-zh/
发邮：public-html-ig-zh@w3.org
订阅：public-html-ig-zh-request@w3.org 标题：subscribe ]]></description>
            <pubDate>2010年11月26日</pubDate>
        </item>
                <item>
            <title>最新消息：W3C将不在更新Web SQL Database</title>
            <link>http://www.w3ctech.com/p/59</link>
            <guid>http://www.w3ctech.com/p/59</guid>
            <category>行业快报</category>
            <description><![CDATA[ 从html中文兴趣小组（public-html-ig-zh@w3.org）得到的消息，在這個月初的W3C TPAC（W3C年会）上，Web Application工作小組作出了一个决定，將Web SQL Database从「工作草案」的狀態变更为「工作小組报告。這标志着Web SQL Database最终将不会成为W3C推荐标准。

W3C将推荐大家使用Web Storage跟Indexed Database API。

Web SQL Database之所以不能成为标准的主要原因是因为SQL不是一个标准。

其实Indexed Database API就是BTree的API而已。 ]]></description>
            <pubDate>2010年11月22日</pubDate>
        </item>
                <item>
            <title>W3C成立WEB EVENTS（事件）工作组</title>
            <link>http://www.w3ctech.com/p/88</link>
            <guid>http://www.w3ctech.com/p/88</guid>
            <category>行业快报</category>
            <description><![CDATA[ 于2010年10月28日，W3C正式成立了WEB EVENTS（事件）工作组。

W3C Web Events（事件）工作组成立的目的是发展关于多点触摸事件（相关的装置包含手写板、电子白板或是类似的输入装置），及高级的涵盖触控装置、键盘输入、鼠标控制及其它输入装置的事件，建造单一简单一贯的模型以定义用户事件（像放大、滚动条、重作、回复）。

谢谢kenny的翻译。 ]]></description>
            <pubDate>2010年11月10日</pubDate>
        </item>
                <item>
            <title>W3C发布针对浏览器的DOM草案</title>
            <link>http://www.w3ctech.com/p/37</link>
            <guid>http://www.w3ctech.com/p/37</guid>
            <category>行业快报</category>
            <description><![CDATA[ W3C于2010年10月7日发布专门针对浏览器的DOM草案，名称为：Web DOM。
详情请查看W3C官方地址：<a href="http://www.w3.org/TR/2010/WD-domcore-20101007/">http://www.w3.org/TR/2010/WD-domcore-20101007/</a> ]]></description>
            <pubDate>2010年11月09日</pubDate>
        </item>
                
    </channel>
</rss>
