<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href='http://feed.planabc.net/styles/feedsky2.xsl' type='text/xsl' ?><!--这是一个由Feedsy提供技术支持的Feed，为了提高读者阅读的体验，以及满足用户美化自己Feed的需要，我们设计了多种精美的Feed模板，提供给大家选择，所有最终呈现出来的样式，皆由用户自愿选择使用，未经许可，任何团体和个人，请不要擅自修改样式或者盗用，这是对于用户选择权的尊重。--><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fs="http://www.feedsky.com/namespace/feed" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link href="http://feed.planabc.net" type="application/rss+xml" rel="self"></atom:link><fs:self_link href="http://feed.feedsky.com/planabc" type="application/rss+xml"></fs:self_link><lastBuildDate>Tue, 07 Sep 2010 06:05:13 GMT</lastBuildDate><title>PlanABC - 怿飞’s Blog</title><description>落草为根—专注前端技术&amp;&amp;关注用户体验</description><image><url>http://www.feedsky.com/feed/planabc/sc/gif</url><title>PlanABC - 怿飞’s Blog</title><link>http://www.planabc.net</link></image><link>http://www.planabc.net</link><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><language>en</language><pubDate>Tue, 07 Sep 2010 08:30:11 GMT</pubDate><item><title>Google DevFest 2010 Beijing 之行</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553729/5157647/1/item.html</link><content:encoded>&lt;p&gt;非常荣幸作为嘉宾参加了 &lt;a href=&quot;http://www.google.com/intl/zh-CN/events/devfests/2010/&quot; target=&quot;_blank&quot; title=&quot;Google DevFest 2010 Beijing&quot;&gt;Google DevFest 2010 Beijing&lt;/a&gt;，感谢 Google 胡坤的邀请，感谢 Google 寒蕊的合作，简单的接触，能够感受到 Google 的开放与细腻，或许这就是 Google 特有的品质。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.planabc.net/wp-content/uploads/2010/09/devfest01.jpg&quot; alt=&quot;Google DevFest 2010 Beijing 嘉宾卡&quot;/&gt;&lt;/p&gt;
&lt;p&gt;下午&lt;a href=&quot;http://www.google.com/intl/zh-CN/events/devfests/2010/schedule.html&quot; target=&quot;_blank&quot; title=&quot;会议日程&quot;&gt;《如何用 HTML5 做应用开发》&lt;/a&gt;的话题，Google 寒蕊 主要分享了 HTML5 的 What ，而我主要针对 HTML5 的 Where、Why 和 How 做了简单的演示。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.planabc.net/wp-content/uploads/2010/09/devfestppt.jpg&quot; alt=&quot;PPT：HTML5 in Action&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.planabc.net/wp-content/uploads/2010/09/devfest02.jpg&quot; alt=&quot;分享《如何用 HTML5 做应用开发》&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.planabc.net/wp-content/uploads/2010/09/devfest03.jpg&quot; alt=&quot;《如何用 HTML5 做应用开发》Q&amp;#038;A 环节&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt; PPT——《HTML5 in Action》 ：&lt;/strong&gt;&lt;a href=&quot;http://www.planabc.net/demo/html5/ppt.html&quot; target=&quot;_blank&quot;&gt;http://www.planabc.net/demo/html5/ppt.html&lt;/a&gt; ，PPT 基于 HTML5 开发，为了最佳效果，建议使用 Chrome 浏览器，小键盘左右键前后翻页。由于原来在本地演示，跨域演示的环境已改变，可以自己模拟。&lt;/p&gt;
&lt;p&gt;会议结束后所有的同事一起合了张影：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.planabc.net/wp-content/uploads/2010/09/devfest04.jpg&quot; alt=&quot;Taobao 同事合影&quot;/&gt;&lt;/p&gt;
&lt;p&gt;另外的收获：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;见到了认识了几年但一直未曾谋面的 Opera &lt;a href=&quot;http://zibin.tehais.com/&quot; target=&quot;_blank&quot; title=&quot;Opera Zibin&quot;&gt;Zibin&lt;/a&gt;，从他那里也获知了他正在向 W3C 申请 &lt;strong&gt;HTML5中文兴趣小组&lt;/strong&gt;，期待好消息。&lt;/li&gt;
&lt;li&gt;从这次的举办中学到了许多不错的会议细节，相信下次 &lt;a href=&quot;http://www.d2forum.org&quot; title=&quot;D2 前端技术论坛&quot; target=&quot;_blank&quot;&gt;D2 前端技术论坛&lt;/a&gt; 的举办，我们将会做得更好。&lt;/li&gt;
&lt;li&gt;见到了熟悉的老朋友 Tencent &lt;a href=&quot;http://www.twinsenliang.net/&quot; target=&quot;_blank&quot; title=&quot;Twinsen Liang&quot;&gt;梁璟彪&lt;/a&gt;，约定明年 &lt;a href=&quot;http://www.d2forum.org&quot; title=&quot;D2 前端技术论坛&quot; target=&quot;_blank&quot;&gt;D2 前端技术论坛&lt;/a&gt;  将与 &lt;a href=&quot;http://www.webrebuild.org/&quot; target=&quot;_blank&quot; title=&quot;WebReBuild &quot;&gt;WebReBuild&lt;/a&gt; 联手合作，明年注定属于前端年。&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=514&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553729/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553729/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553729/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553729/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/09/07/google_devfest_2010_beijing/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>非常荣幸作为嘉宾参加了 Google DevFest 2010 Beijing，感谢 Google 胡坤的邀请，感谢 Google 寒蕊的合作，简单的接触，能够感受到 Google 的开放与细腻，或许这就是 Google 特有的品质。 下午《如何用 HTML5 做应用开发》的话题，Google 寒蕊 主要分享了 HTML5 的 What ，而我主要针对 HTML5 的 Where、Why 和 How 做了简单的演示。 PPT——《HTML5 in Action》 ：http://www.planabc.net/demo/html5/ppt.html ，PPT 基于 HTML5 开发，为了最佳效果，建议使用 Chrome 浏览器，小键盘左右键前后翻页。由于原来在本地演示，跨域演示的环境已改变，可以自己模拟。 会议结束后所有的同事一起合了张影： 另外的收获： 见到了认识了几年但一直未曾谋面的 Opera Zibin，从他那里也获知了他正在向 W3C 申请 HTML5中文兴趣小组，期待好消息。 从这次的举办中学到了许多不错的会议细节，相信下次 D2 前端技...&lt;img src=&quot;http://www1.feedsky.com/t1/410553729/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553729/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553729/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553729/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>beijing</category><category>devfest</category><category>我的生活</category><category>google</category><pubDate>Tue, 07 Sep 2010 14:05:13 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/09/07/google_devfest_2010_beijing/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=514</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/09/07/google_devfest_2010_beijing/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553729/5157647</fs:itemid></item><item><title>浅谈 Mousewheel 事件</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553730/5157647/1/item.html</link><content:encoded>&lt;p&gt;当需要制作转动鼠标滚轮放大页面字体这样的交互效果时，会用到 Mousewheel 事件。其实在大多数浏览器（IE6, IE7, IE8, Opera 10+, Safari 5+）中，都提供了 &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms536951%28VS.85%29.aspx&quot; target=&quot;_blank&quot; title=&quot;onmousewheel Event&quot;&gt;&amp;#8220;mousewheel&amp;#8221;&lt;/a&gt; 事件。但杯具的是 Firefox 3.5+ 却不支持此事件，不过庆幸 Firefox 3.5+ 中提供了另外一个等同的事件：&amp;#8221;DOMMouseScroll&amp;#8221; （&lt;a href=&quot;http://www.planabc.net/demo/event/mousewheel.html&quot; target=&quot;_blank&quot; title=&quot;Mousewheel Event in JavaScript&quot;&gt;事件和事件属性的测试案例&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;OK，我们现在已经知道了不同浏览器之间实现的差别，兼容代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var addEvent = (function(){
        if (window.addEventListener) {
            return function(el, sType, fn, capture) {
                el.addEventListener(sType, fn, (capture));
            };
        } else if (window.attachEvent) {
            return function(el, sType, fn, capture) {
                el.attachEvent(&quot;on&quot; + sType, fn);
            };
        } else {
            return function(){};
        }
    })(),
    // isFirefox 是伪代码，大家可以自行实现
    mousewheel = isFirefox ? &quot;DOMMouseScroll&quot; : &quot;mousewheel&quot;;

// object 也是伪代码，你需要注册 Mousewheel 事件的元素
addEvent(object, mousewheel, function(event){
    event = window.event || event;
    // todo something
}, false);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们再回到要实现的交互效果上，现在还有其他一些问题需要来解决：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;页面字体到底是放大还是缩小呢？ ==&gt; 鼠标滚轮是向上滚动还是向下滚动呢？&lt;/li&gt;
&lt;li&gt;页面字体缩放的倍数到底是多少呢？ ==&gt; 鼠标滚轮滚动的幅度大小是多少呢？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;还好，我们可以通过 event 的某些属性值得到这些信息：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;#8220;mousewheel&amp;#8221; 事件中的 &amp;#8220;event.wheelDelta&amp;#8221; 属性值：返回的值，如果是正值说明滚轮是向上滚动，如果是负值说明滚轮是向下滚动；返回的值，均为 120 的倍数，即：幅度大小 = 返回的值 / 120。 &lt;/li&gt;
&lt;li&gt;&amp;#8220;DOMMouseScroll&amp;#8221; 事件中的 &amp;#8220;event.detail&amp;#8221; 属性值：返回的值，如果是负值说明滚轮是向上滚动（与 &amp;#8220;event.wheelDelta&amp;#8221; 正好相反），如果是正值说明滚轮是向下滚动；返回的值，均为 3 的倍数，即：幅度大小 = 返回的值 / 3。 &lt;/li&gt;
&lt;li&gt;&amp;#8220;mousewheel&amp;#8221; 事件在 Opera 10+ 中却是个特例，既有 &amp;#8220;event.wheelDelta&amp;#8221; 属性，也有 &amp;#8220;event.detail&amp;#8221; 属性。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;注：上面第三点，在&lt;a href=&quot;http://www.javascriptkit.com/javatutors/onmousewheel.shtml&quot; target=&quot;_blank&quot; title=&quot;The onmousewheel event of JavaScript&quot;&gt;《The onmousewheel event of JavaScript》&lt;/a&gt;一文中有这样一段批注：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;In Opera, &amp;#8220;detail&amp;#8221; returns the same value as it does in FF, so for the big O you should rely on &amp;#8220;detail&amp;#8221; instead of &amp;#8220;wheelDelta&amp;#8221;, which depending on the Opera version may return a different value than in IE&amp;#8217;s.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;但经测试， Opera 9+ 和 Opera 10+ 中的 event.wheelDelta 属性与其他浏览器中的表现完全一致，未发现异常与错误，从接口角度来说，代码中应优先使用 &amp;#8220;event.wheelDelta&amp;#8221; 属性。&lt;/p&gt;
&lt;p&gt;此时代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var addEvent = (function(){
        if (window.addEventListener) {
            return function(el, sType, fn, capture) {
                el.addEventListener(sType, fn, (capture));
            };
        } else if (window.attachEvent) {
            return function(el, sType, fn, capture) {
                el.attachEvent(&quot;on&quot; + sType, fn);
            };
        } else {
            return function(){};
        }
    })(),
    stopEvent: function(event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }

        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    zoomIn = function(){},
    zoomOut = function(){},
    // isFirefox 是伪代码，大家可以自行实现
    mousewheel = isFirefox ? &quot;DOMMouseScroll&quot; : &quot;mousewheel&quot;;

// object 是伪代码，你需要注册 Mousewheel 事件的元素
addEvent(object, mousewheel, function(event){
    var delta = 0;
    event = window.event || event;
    stopEvent(event);

    delta = event.wheelDelta ? (event.wheelDelta / 120) : (- event.detail / 3);
    // zoomIn, zoomOut 是伪代码，需要实现的缩放事件
    delta &gt; 0 ? zoomIn(delta): zoomOut(Math.abs(delta));
} , false);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;事件和事件属性的测试案例：&lt;a href=&quot;http://www.planabc.net/demo/event/mousewheel.html&quot; target=&quot;_blank&quot; title=&quot;Mousewheel Event in JavaScript&quot;&gt;http://www.planabc.net/demo/event/mousewheel.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;扩展阅读：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://adomas.org/javascript-mouse-wheel/&quot; target=&quot;_blank&quot; title=&quot;Mouse wheel programming in JavaScript&quot;&gt;《Mouse wheel programming in JavaScript》&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=500&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553730/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553730/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553730/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553730/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/08/12/mousewheel_event_in_javascript/feed/</wfw:commentRss><slash:comments>7</slash:comments><description>当需要制作转动鼠标滚轮放大页面字体这样的交互效果时，会用到 Mousewheel 事件。其实在大多数浏览器（IE6, IE7, IE8, Opera 10+, Safari 5+）中，都提供了 &amp;#8220;mousewheel&amp;#8221; 事件。但杯具的是 Firefox 3.5+ 却不支持此事件，不过庆幸 Firefox 3.5+ 中提供了另外一个等同的事件：&amp;#8221;DOMMouseScroll&amp;#8221; （事件和事件属性的测试案例）。 OK，我们现在已经知道了不同浏览器之间实现的差别，兼容代码如下： var addEvent = (function(){ if (window.addEventListener) { return function(el, sType, fn, capture) { el.addEventListener(sType, fn, (capture)); }; } else if (window.attachEvent) { return function(el, sType, fn, capture) { el.attachEvent(&quot;on&quot; + sType, fn); }; } else { [......&lt;img src=&quot;http://www1.feedsky.com/t1/410553730/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553730/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553730/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553730/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>mouse</category><category>JS/Ajax/AS/Flex</category><category>event</category><pubDate>Thu, 12 Aug 2010 19:48:19 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/08/12/mousewheel_event_in_javascript/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=500</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/08/12/mousewheel_event_in_javascript/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553730/5157647</fs:itemid></item><item><title>在线 Base64 编/解码小工具</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553731/5157647/1/item.html</link><content:encoded>&lt;p&gt;抽时间做了一个简单的基于 JavaScript 的在线 Base64 编/解码小工具：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.planabc.net/lab/tools/base64.html&quot; title=&quot;Base64 Encoding or Decoding in Javascript&quot; target=&quot;_blank&quot;&gt;http://www.planabc.net/lab/tools/base64.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;原理详见上篇文章：&lt;a href=&quot;http://www.planabc.net/2010/07/21/base64_encoding_in_javascript_part_i/&quot; target=&quot;_blank&quot; title=&quot;JavaScript 中的 Base64 编码（一）：Encoding &quot;&gt;《JavaScript 中的 Base64 编码（一）：Encoding 》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注：&lt;/strong&gt;对于下面的代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;各浏览器原生的解码方法处理不太一致，Opera 比较智能能够处理此情形，但 Firefox、Safari 和 Chrome 却无法处理。&lt;/p&gt;
&lt;p&gt;出现上面代码的原因为：&lt;strong&gt;规则约定  Base64 编码过程每76个字符加一个换行符&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt; Firefox、Safari 和 Chrome 下的修复非常简单（对输入的字符去除换行符等）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;text = text.replace(/\s*/g, ''); //Fix Firefox/Safari/Chrom bug: MultiLine&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如有 BUG 欢迎随时联系：blankzheng#gmail.com&lt;/p&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=484&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553731/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553731/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553731/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553731/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/07/22/online_base64_encoding_or_decoding_tools/feed/</wfw:commentRss><slash:comments>2</slash:comments><description>抽时间做了一个简单的基于 JavaScript 的在线 Base64 编/解码小工具： http://www.planabc.net/lab/tools/base64.html 原理详见上篇文章：《JavaScript 中的 Base64 编码（一）：Encoding 》 注：对于下面的代码： TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4= 各浏览器原生的解码方法处理不太一致，Opera 比较智能能够处理此情形，但 Firefox、Safari 和 Chrome 却无法处理。 出现上面代码的原因为：规则约定 Base64 编码过程每76个字符加一个换行符。 Firefox、Safari 和 Chrome 下的修复非常简单（对输入的字符去除换行符等）： text = text.replace(/\s*/g, ''); //Fix...&lt;img src=&quot;http://www1.feedsky.com/t1/410553731/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553731/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553731/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553731/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>base64</category><category>JS/Ajax/AS/Flex</category><pubDate>Thu, 22 Jul 2010 17:03:42 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/07/22/online_base64_encoding_or_decoding_tools/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=484</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/07/22/online_base64_encoding_or_decoding_tools/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553731/5157647</fs:itemid></item><item><title>JavaScript 中的 Base64 编码（一）：Encoding</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553732/5157647/1/item.html</link><content:encoded>&lt;p&gt;除了IE浏览器，其他所有主流的浏览器均支持原生的 Base64 编码：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;btoa(text)&lt;/strong&gt; &amp;#8211; base64 encodes text.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;atob(text)&lt;/strong&gt; &amp;#8211; base64 decodes text.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而对于 IE 我们可以根据已知的 Base64 编码原理进行编写：&lt;/p&gt;
&lt;p&gt;Base64 编码将每三个 8Bit 的字节（&lt;strong&gt;注：&lt;/strong&gt;由于要求输入的字符为 8Bit 字节，故范围应该在 ASCII 字符范围内，即：\u0000-\u00ff）转换为四个 6Bit 的字节（3*8 = 4*6 = 24），然后在每个 6Bit 字节前添两位高位 0，组成四个 8Bit 的字节，最后再将每个 8Bit 字节转换成十进制的数字，对应 Base64 编码表（为了保证所输出的编码为可读字符，Base64制定了一个编码表，以便进行统一转换，编码表的大小为 2^6=64，即 Base64 名称的由来）输出编码后的字符。&lt;/p&gt;
&lt;p&gt;如果原字节不足 3 的倍数，则用 0 填充，输出字符使用“=”，因此编码后输出的文本末尾可能会出现 1 或 2 个“=”（余数 = 原文字节数 MOD 3 ，如果余数为 1，则要补 2 个“=”，为 2，则补 1 个“=”）。&lt;/p&gt;
&lt;style type=&quot;text/css&quot;&gt;
/* base64table class for skinning normal tables */
table.base64table {
    margin: 1em 1em 1em 30px;
    background: #f9f9f9;
    border: 1px #aaa solid;
}
.base64table th, .base64table td {
    border: 1px #aaa solid;
    padding: 0.2em;
}
.base64table th {
    background: #f2f2f2;
    text-align: center;
}
.base64table caption {
    font-weight: bold;
}
&lt;/style&gt;
&lt;table style=&quot;text-align: center;&quot; class=&quot;base64table&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th colspan=&quot;11&quot;&gt; &lt;strong&gt;Base64 编码表&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;Value&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Char&lt;/th&gt;
&lt;td rowspan=&quot;18&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;th scope=&quot;col&quot;&gt;Value&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Char&lt;/th&gt;
&lt;td rowspan=&quot;18&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;th scope=&quot;col&quot;&gt;Value&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Char&lt;/th&gt;
&lt;td rowspan=&quot;18&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;th scope=&quot;col&quot;&gt;Value&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Char&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Q&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;g&lt;/td&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;h&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;S&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;j&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;z&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;U&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;k&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;V&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;l&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;G&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;W&lt;/td&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;m&lt;/td&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;I&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;o&lt;/td&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;J&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;Z&lt;/td&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;K&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;q&lt;/td&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;59&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;M&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;c&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;d&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;t&lt;/td&gt;
&lt;td&gt;61&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;e&lt;/td&gt;
&lt;td&gt;46&lt;/td&gt;
&lt;td&gt;u&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;P&lt;/td&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;td&gt;f&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;v&lt;/td&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;/&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;字符：               f        2         e
ASCII：              102      50        101
3个8Bit字节：        01100110 00110010  01100101
4个6Bit字节：          011001   100011    001001    100101
高位补0：            00011001 00100011  00001001  00100101
十进制：             25       35        9         37
对应码表值：         Z        j         J         l

最终： btoa('f2e') = ZjJl&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;字符：              b        a        s        e
ASCII：             98       97       115      101
3个8Bit字节：       01100010 01100001 01110011 01100101 00000000 00000000
4个6Bit字节：         011000   100110   000101   110011   011001   010000    000000   000000
高位补0：           00011000 00100110 00000101 00110011 00011001 00010000 00000000 00000000
十进制：            24       38       5        51       25       16
对应码表值：        Y        m        F        z        Z        Q        =        =

最终： btoa('base') = YmFzZQ==&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果将上面的 Base64 编码原理换成接近于编程的思维，过程大致如下（以f2e为例）：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注：&lt;/strong&gt;Base64 编码表我们可以简化为字符串，并通过其进行位置索引：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;table = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;第一步：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;第一个字符 f（102 -&gt; 01100110）通过右移 2 位（first &gt;&gt; 2）获得第一个目标字符（00011001 -&gt; 25），索引编码表中对应的目标字符 Z（table.charAt(first &gt;&gt; 2)）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;第二步：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将第一个字符 f（102 -&gt; 01100110）与 3（00000011）进行 AND 运算（first &amp;#038; 3)）:
&lt;pre&gt;&lt;code&gt;    01100110
AND 00000011
------------
    00000010&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;第一个字符运算后（00000010）再左移 4 位（(first &amp;#038; 3) &lt;&lt; 4），得：00100000。&lt;/li&gt;
&lt;li&gt;将第二个字符 2 （50 -&gt; 00110010）右移 4 位（second &gt;&gt; 4），得：00000011。&lt;/li&gt;
&lt;li&gt;最后将运算后的两个字符进行 OR 运算（(first &amp;#038; 3) &lt;&lt; 4 | second &gt;&gt; 4）：
&lt;pre&gt;&lt;code&gt;    00100000
OR  00000011
------------
    00100011&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;获得第二个目标字符（00100011 -&gt; 35），索引编码表中对应的目标字符 j（table.charAt((first &amp;#038; 3) &lt;&lt; 4 | second &gt;&gt; 4)）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;第三步：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将第二个字符 2 （50 -&gt; 00110010）与 15（00001111，十六进制：0x0f）进行 AND 运算（second &amp;#038; 0x0f）:
&lt;pre&gt;&lt;code&gt;    00110010
AND 00001111
------------
    00000010
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;第二个字符运算后（00000010）再左移 2 位（(second &amp;#038; 0x0f) &lt;&lt; 2），得：00001000。&lt;/li&gt;
&lt;li&gt;第三个字符 e（101 -&gt; 01100101）右移 6 位（third &gt;&gt; 6），得：00000001。&lt;/li&gt;
&lt;li&gt;最后将运算后的两个字符进行 OR 运算（(second &amp;#038; 0x0f) &lt;&lt; 2 | third &gt;&gt; 6）：
&lt;pre&gt;&lt;code&gt;    00001000
OR  00000001
------------
    00001001&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;即获得第三个目标字符（00001001 -&gt; 9），索引编码表中对应的目标字符 J（table.charAt((second &amp;#038; 0x0f) &lt;&lt; 2 | third &gt;&gt; 6)）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;第四步：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;取第三个字符 e（101 -&gt; 01100101）的右 6 位，即与 63 （00111111，16进制：0x3f）进行 AND 运算（third &amp;#038; 0x3f）：
&lt;pre&gt;&lt;code&gt;    01100101
AND 00111111
------------
    00100101&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;获得第四个目标字符（00100101 -&gt; 37），索引编码表中对应的目标字符 l（table.charAt(third &amp;#038; 0x3f)）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;异常情况：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当第二个字符不存在时（即：余数 = 原文字节数 MOD 3 ，余数为 1），截止至第二步的第 2 小步，然后在最终输出的目标字符后添加两个“=”。&lt;/li&gt;
&lt;li&gt;当第三个字符不存在时（即：余数 = 原文字节数 MOD 3 ，余数为 2），截止至第三步的第 2 小步，然后在最终输出的目标字符后添加两个“=”。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;代码实现如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if(!window.btoa) {
    window.btoa  = function(text) {
        if (/([^\u0000-\u00ff])/.test(text)) return;
        var table = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;,
            i = 0,
            cur, prev, byteNum,
            result=[];    

        while(i &lt; text.length){
            cur = text.charCodeAt(i);
            byteNum = (i+1) % 3;

            switch(byteNum){
                case 1: //first byte
                    result.push(table.charAt(cur &gt;&gt; 2));
                    break;

                case 2: //second byte
                    result.push(table.charAt((prev &amp;#038; 3) &lt;&lt; 4 | (cur &gt;&gt; 4)));
                    break;

                case 0: //third byte
                    result.push(table.charAt((prev &amp;#038; 0x0f) &lt;&lt; 2 | (cur &gt;&gt; 6)));
                    result.push(table.charAt(cur &amp;#038; 0x3f));
                    break;
            }

            prev = cur;
            i++;
        }

        if (byteNum == 1){
            result.push(table.charAt((prev &amp;#038; 3) &lt;&lt; 4));
            result.push(&quot;==&quot;);
        } else if (byteNum == 2){
            result.push(table.charAt((prev &amp;#038; 0x0f) &lt;&lt; 2));
            result.push(&quot;=&quot;);
        }

        return result.join(&quot;&quot;);
    }
}&lt;/code&gt; &lt;/pre&gt;
&lt;p&gt;-----------------------------------------------------------------------------&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;下篇：《JavaScript 中的 Base64 编码（二）：Decoding》&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;-----------------------------------------------------------------------------&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;扩展阅读：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nczonline.net/blog/2009/12/08/computer-science-in-javascript-base64-encoding/&quot; target=&quot;_blank&quot; title=&quot;Computer science in JavaScript: Base64 encoding&quot;&gt;《Computer science in JavaScript: Base64 encoding》&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=447&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553732/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553732/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553732/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553732/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/07/21/base64_encoding_in_javascript_part_i/feed/</wfw:commentRss><slash:comments>4</slash:comments><description>除了IE浏览器，其他所有主流的浏览器均支持原生的 Base64 编码： btoa(text) &amp;#8211; base64 encodes text. atob(text) &amp;#8211; base64 decodes text. 而对于 IE 我们可以根据已知的 Base64 编码原理进行编写： Base64 编码将每三个 8Bit 的字节（注：由于要求输入的字符为 8Bit 字节，故范围应该在 ASCII 字符范围内，即：\u0000-\u00ff）转换为四个 6Bit 的字节（3*8 = 4*6 = 24），然后在每个 6Bit 字节前添两位高位 0，组成四个 8Bit 的字节，最后再将每个 8Bit 字节转换成十进制的数字，对应 Base64 编码表（为了保证所输出的编码为可读字符，Base64制定了一个编码表，以便进行统一转换，编码表的大小为 2^6=64，即 Base64 名称的由来）输出编码后的字符。 如果原字节不足 3 的倍数，则用 0 填充，输出字符使用“=”，因此编码后输出的文本末尾可能会出现 1 或 2 个“=”（余数 = 原文字节数 [.....&lt;img src=&quot;http://www1.feedsky.com/t1/410553732/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553732/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553732/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553732/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>base64</category><category>JS/Ajax/AS/Flex</category><category>javascript</category><pubDate>Wed, 21 Jul 2010 23:05:03 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/07/21/base64_encoding_in_javascript_part_i/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=447</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/07/21/base64_encoding_in_javascript_part_i/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553732/5157647</fs:itemid></item><item><title>淘宝海量图片存储与CDN系统</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553733/5157647/1/item.html</link><content:encoded>&lt;p&gt;&lt;object id=&quot;__sse4508477&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cdn-100615125200-phpapp02&amp;#038;stripped_title=cdn-4508477&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed name=&quot;__sse4508477&quot; src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cdn-100615125200-phpapp02&amp;#038;stripped_title=cdn-4508477&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=443&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553733/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553733/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553733/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553733/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/06/30/storage_and_cdn_in_taobao/feed/</wfw:commentRss><slash:comments>9</slash:comments><description>...&lt;img src=&quot;http://www1.feedsky.com/t1/410553733/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553733/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553733/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553733/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>taobao</category><category>cdn</category><category>网站优化</category><pubDate>Wed, 30 Jun 2010 13:44:17 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/06/30/storage_and_cdn_in_taobao/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=443</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/06/30/storage_and_cdn_in_taobao/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553733/5157647</fs:itemid></item><item><title>用 JavaScript 解数学题</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553734/5157647/1/item.html</link><content:encoded>&lt;p&gt;&lt;strong&gt;题目：&lt;/strong&gt;一个六位数，分别用2，3，4，5，6乘它，得到的五个新数仍是由原数中的六个数字组成，只是位置不同，则此六位数是多少？&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function evaluate() {
    var multiplier = [2,3,4,5,6],
        sortNumber = function (number) {
            return parseInt((number + '').split('').sort().join(''), 10);
        },
        gameOver = false, // 判断是否已经找到，如果找到，结束循环
        determine = function(origin) {
            var result, i, len = multiplier.length;
            for( i = 0; i &lt; len; i++ ) {
                result = origin * multiplier[i];
                if (result &lt; 100000 || result &gt; 999999 || sortNumber(result) !== sortNumber(origin)) {
                    return;
                }
                if(i === (len-1)){
                    gameOver = true;
                    alert('此六位数是 ' + origin);
                }
            }
        };

    // Math.floor(1000000/6) 缩小范围
    for(var j = Math.floor(1000000/6); j &gt;= 100000  &amp;#038;&amp;#038; !gameOver; j--) {
        determine(j);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;扩展阅读：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://scriptfans.javaeye.com/blog/100114&quot; target=&quot;_blank&quot; title=&quot;用python解一道奥数题（小学三年级）&quot;&gt;《用python解一道奥数题（小学三年级）》&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=431&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553734/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553734/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553734/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553734/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/05/26/solving_the_mathematical_problem_using_javascript/feed/</wfw:commentRss><slash:comments>21</slash:comments><description>题目：一个六位数，分别用2，3，4，5，6乘它，得到的五个新数仍是由原数中的六个数字组成，只是位置不同，则此六位数是多少？ function evaluate() { var multiplier = [2,3,4,5,6], sortNumber = function (number) { return parseInt((number + '').split('').sort().join(''), 10); }, gameOver = false, // 判断是否已经找到，如果找到，结束循环 determine = function(origin) { var result, i, len = multiplier.length; for( i = 0; i &lt; len; i++ ) { result = origin * multiplier[i]; if (result &lt; 100000 &amp;#124;&amp;#124; result [......&lt;img src=&quot;http://www1.feedsky.com/t1/410553734/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553734/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553734/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553734/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>JS/Ajax/AS/Flex</category><category>javascript</category><pubDate>Wed, 26 May 2010 18:42:37 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/05/26/solving_the_mathematical_problem_using_javascript/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=431</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/05/26/solving_the_mathematical_problem_using_javascript/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553734/5157647</fs:itemid></item><item><title>各浏览器的并行连接数（同域名）</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553735/5157647/1/item.html</link><content:encoded>&lt;table cellspacing=&quot;6&quot; cellpadding=&quot;4&quot; border=&quot;0&quot; style=&quot;margin:10px 0 10px 30px&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Browser&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;HTTP/1.1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;HTTP/1.0&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IE 6,7&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;2&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IE 8&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;6&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox 3+&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;6&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safari 3+&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chrome 3+&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opera 10+&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;扩展阅读：&lt;a href=&quot;http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/&quot; target=&quot;_blank&quot; title=&quot;Roundup on Parallel Connections&quot;&gt;《Roundup on Parallel Connections》&lt;/a&gt;&lt;/p&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=419&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553735/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553735/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553735/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553735/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/05/07/connections_per_server_supported_by_current_browsers/feed/</wfw:commentRss><slash:comments>12</slash:comments><description>Browser HTTP/1.1 HTTP/1.0 IE 6,7 2 4 IE 8 6 6 Firefox 3+ 6 6 Safari 3+ 4 4 Chrome 3+ 4 4 Opera 10+ 4 4 扩展阅读：《Roundup on Parallel Connections...&lt;img src=&quot;http://www1.feedsky.com/t1/410553735/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553735/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553735/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553735/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>网站优化</category><category>优化</category><pubDate>Fri, 07 May 2010 10:21:27 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/05/07/connections_per_server_supported_by_current_browsers/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=419</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/05/07/connections_per_server_supported_by_current_browsers/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553735/5157647</fs:itemid></item><item><title>与 Function 和  Object 相关的有趣代码</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553736/5157647/1/item.html</link><content:encoded>&lt;p&gt;代码片段一：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alert(Function instanceof Object); // true
alert(Object instanceof Function); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Function 是 Object 的实例，Object 也是 Function 的实例，好“纠缠”的关系。&lt;/p&gt;
&lt;p&gt;代码片段一：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alert(Object.forEach); // undefined

Function.prototype.forEach = function(object, block, context) {
    for (var key in object) {
        if (typeof this.prototype[key] == &quot;undefined&quot;) {
            block.call(context, object[key], key, object);
        }
    }
};

alert(Object.forEach);
alert(Function.forEach);
alert(Object.forEach === Function.forEach); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;给 Function 设置的原型方法 forEach，“有趣”的是 Object 也能够获取。&lt;/p&gt;
&lt;p&gt;至于为什么可以从 &lt;a href=&quot;http://www.mollypages.org/misc/js.mp&quot; target=&quot;_blank&quot; title=&quot;JavaScript Object layout&quot;&gt;JavaScript Object layout&lt;/a&gt; 图中获取部分解答：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.planabc.net/wp-content/uploads/2010/05/javascript_object_layout.jpg&quot; alt=&quot;JavaScript Object layout&quot; / &gt;&lt;/p&gt;
&lt;p&gt;看懂上图了没？如果看懂了，留道思考题给大家：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function Foo() {};
var foo = new Foo();

alert(foo instanceof Foo); // ?
alert(foo instanceof Object); // ?
alert(foo instanceof Function); // ?
alert(Foo instanceof Function); // ?
alert(Foo instanceof Object); // ?&lt;/code&gt;&lt;/pre&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=411&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553736/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553736/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553736/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553736/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/05/06/interesting_code_associated_with_function_and_object/feed/</wfw:commentRss><slash:comments>10</slash:comments><description>代码片段一： alert(Function instanceof Object); // true alert(Object instanceof Function); // true Function 是 Object 的实例，Object 也是 Function 的实例，好“纠缠”的关系。 代码片段一： alert(Object.forEach); // undefined Function.prototype.forEach = function(object, block, context) { for (var key in object) { if (typeof this.prototype[key] == &quot;undefined&quot;) { block.call(context, object[key], key, object); } } }; alert(Object.forEach); alert(Function.forEach); alert(Object.forEach === Function.forEach); // true 给 [......&lt;img src=&quot;http://www1.feedsky.com/t1/410553736/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553736/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553736/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553736/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>function</category><category>JS/Ajax/AS/Flex</category><category>object</category><pubDate>Thu, 06 May 2010 11:33:05 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/05/06/interesting_code_associated_with_function_and_object/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=411</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/05/06/interesting_code_associated_with_function_and_object/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553736/5157647</fs:itemid></item><item><title>学习 YUI3 中的沙箱机制</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553737/5157647/1/item.html</link><content:encoded>&lt;p&gt;简化了一下 &lt;a href=&quot;http://developer.yahoo.com/yui/3/api/yui.js.html&quot; target=&quot;_blank&quot; title=&quot;API: yui yui.js (YUI Library)&quot;&gt;YUI3 中的沙箱实现&lt;/a&gt; 方式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (typeof Sandbox === 'undefined' || !Sandbox) {
    Sandbox = function(o) {
        var self = this;

        if (!(self instanceof Sandbox)) { // 允许没有 new 操作符的实例化
            return new Sandbox(o);
        } else {
            self._init();
            self._config(o);

            // 预加载某些指定模块
            /* self._setup(); */

            // 返回实例本身，支持链式模式
            return self;
        }
    };
}

// Sandbox的（类）静态属性
Sandbox.Env = {
    /* sidx: 0 , */
    mods: {}
};

(function() {
    var p, i,
        SLICE         = Array.prototype.slice,
        /* instances     = {}, */
        time          = new Date().getTime(),
        win           = window,
        doc           = document;

    Sandbox.prototype = {

        // 格式化配置参数
        // NOTE：本着简单适用的原则，取消了原先 YUI 中对 loader 的支持
        _config: function(o) {

            var c = this.config, i, j, m, mods;

            o = o || {};

            // mods = c.modules;

            for (i in o) {
                if (i == 'win') {
                    c[i]  = o[i].contentWindow || o[i];
                    c.doc = c[i].document;
                } else {
                    c[i]  = o[i];
                }
            }
        },

        /**
         * 初始化沙箱实例
         * @private
         */
        _init: function() {

            var self  = this,
                G_Env = Sandbox.Env,
                Env   = self.Env;

            if(!Env) {
                self.Env = {
                    mods: {},
                    _used: {},
                    _attached: {},
                    _loaded: {}
                };

                Env = self.Env;

                /* if (G_Env &amp;#038;&amp;#038; self !== Sandbox ) {
                    Env._sidx  = ++ G_Env.sidx;
                    Env._guid = ('sandbox_' + Env._sidx + '_' + time).replace(/\./g, '_');
                }

                self.id = Env._guid;
                instances[self.id] = self; */
            }

            self.constructor = Sandbox;

            self.config = {
                win: win || {},
                doc: doc || {}
            };

        },

        // 预留预加载某些指定模块，接口可根据实际需要扩展
        /* _setup: function(o) {}, */

        /**
         * 添加模块
         * @method add
         * @param name {string} 模块名
         * @param fn {Function} 模块对应的函数
         * @param version {string}
         * @param details 可选配置：
         *     requires   -  {array}  在本模块执行之前附加的必须的模块数组
         *     use  - {array} 在本模块执行之后附加的模块数组
         *
         */
        add: function(name, fn, details) {
            Sandbox.Env.mods[name] = {
                name: name,
                fn: fn,
                details: details || {}
            };

            return this; // chain support
        },

        /**
         * 执行与 Sandbox 实例相关联的模块：details.requires--》fn--》details.use
         * @method _attach
         * @param r {array} 模块列表数组
         * @private
         */

        _attach: function(r) {

            var mods = Sandbox.Env.mods,
                self = this,
                attached = self.Env._attached,
                i, l = r.length, name, m, fn, d, req, use;

            for (i = 0; i &lt; l; i = i+1) {

                name = r[i];
                m    = mods[name];

                if (!attached[name] &amp;#038;&amp;#038; m) {

                    attached[name] = true;

                    fn  = m.fn;
                    d   = m.details;
                    req = d.requires;
                    use = d.use;

                    if (req) {
                        self._attach(req);
                    }

                    if (fn) {
                        fn(self);
                    }

                    if (use) {
                        self._attach(use);
                    }
                }
            }

        },

        /**
         * 绑定模块至 Sandbox 实例
         * @param modules* {string} 1-n 个模块 (uses arguments array)
         * @param *callback {function} callback function  如果包括，必须是最后一个参数。
         *
         * Sandbox().use('planabc.net')
         * Sandbox().use('planabc.net',function(){})
         * Sandbox().use('planabc.net','planabc.com')
         * Sandbox().use('planabc.net','planabc.com',function(){})
         * Sandbox().use('*'); // use all available modules
         *
         */
        use: function() {

            var self = this,
                a = SLICE.call(arguments, 0),
                mods = Sandbox.Env.mods,
                used = self.Env._used,
                loader,
                firstArg = a[0],
                callback = a[a.length-1],
                k, i, l,
                r = [],
                process = function(name) {

                    // 添加模块至附加的模块列表
                    r.push(name);

                    // 一个模块仅附加一次
                    if (used[name]) {
                        return;
                    }

                    var m = mods[name], req, use, j, jl, t, tl,
                        d = m.details;

                    if (m) {
                        used[name] = true;

                        req = d.requires;
                        use = d.use;
                    }

                    // 附加上 requires 模块
                    if (req) {
                        for (j = 0,jl = req.length ; j &lt; jl; j = j + 1) {
                            process(req[j]);
                        }
                    }

                    // 附加上 use 模块
                    if (use) {
                        for (t = 0, tl = use.length; t &lt; tl; t = t + 1) {
                            process(use[t]);
                        }
                    }

                },

                onComplete;

            if (typeof callback === 'function') {
                a.pop();
            } else {
                callback = null;
            }

            onComplete = function() {
                if (callback) {
                    callback(self);
                }
            };

            // Sandbox().use('*');
            if (firstArg === &quot;*&quot;) {
                a = [];
                for (k in mods) {
                    if (mods.hasOwnProperty(k)) {
                        a.push(k);
                    }
                }

                if (callback) {
                    a.push(callback);
                }

                return self.use.apply(self, a);
            }

            l = a.length;

            // 处理所有必须和附加的模块
            for (i = 0; i &lt; l; i = i + 1) {
                process(a[i]);
            }

            self._attach(r);
            onComplete();

            return self; // chain support
        }
    };

})();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试页面：&lt;a href=&quot;http://www.planabc.net/lab/yui/sandbox.html&quot; target=&quot;_blank&quot; title=&quot;YUI3 中的沙箱机制&quot;&gt;http://www.planabc.net/lab/yui/sandbox.html&lt;/a&gt;&lt;/p&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=403&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553737/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553737/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553737/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553737/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/04/08/study_sandbox_pattern_in_yui3/feed/</wfw:commentRss><slash:comments>6</slash:comments><description>简化了一下 YUI3 中的沙箱实现 方式： if (typeof Sandbox === 'undefined' &amp;#124;&amp;#124; !Sandbox) { Sandbox = function(o) { var self = this; if (!(self instanceof Sandbox)) { // 允许没有 new 操作符的实例化 return new Sandbox(o); } else { self._init(); self._config(o); // 预加载某些指定模块 /* self._setup(); */ // 返回实例本身，支持链式模式 return self; } }; } // Sandbox的（类）静态属性 Sandbox.Env = { /* [......&lt;img src=&quot;http://www1.feedsky.com/t1/410553737/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553737/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553737/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553737/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>pattern</category><category>YUI3</category><category>JS/Ajax/AS/Flex</category><category>YUI</category><pubDate>Thu, 08 Apr 2010 20:40:07 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/04/08/study_sandbox_pattern_in_yui3/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=403</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/04/08/study_sandbox_pattern_in_yui3/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553737/5157647</fs:itemid></item><item><title>前端 JavaScript 相关的小Tips</title><link>http://item.feedsky.com/~feedsky/planabc/~7049616/410553738/5157647/1/item.html</link><content:encoded>&lt;p&gt;受 SNS 后台开发同学的邀请，做的一次小分享，希望够简单、明了、有效。其实在给别人分享的同时，自己也能收获很多！&lt;/p&gt;
&lt;p&gt;    &lt;object width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jstips-100401005855-phpapp01&amp;#038;stripped_title=javascript-tips&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jstips-100401005855-phpapp01&amp;#038;stripped_title=javascript-tips&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;img src=&quot;http://www.planabc.net/?ak_action=api_record_view&amp;id=398&amp;type=feed&quot; alt=&quot;&quot; /&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/410553738/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553738/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553738/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553738/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.planabc.net/2010/04/01/some_tips_for_using_javascript/feed/</wfw:commentRss><slash:comments>25</slash:comments><description>受 SNS 后台开发同学的邀请，做的一次小分享，希望够简单、明了、有效。其实在给别人分享的同时，自己也能收获很多...&lt;img src=&quot;http://www1.feedsky.com/t1/410553738/planabc/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/planabc/~7049616/410553738/5157647/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/planabc/410553738/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/planabc/410553738/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>JS/Ajax/AS/Flex</category><category>json</category><category>javascript</category><category>ajax</category><pubDate>Thu, 01 Apr 2010 15:27:07 +0800</pubDate><author>怿飞</author><comments>http://www.planabc.net/2010/04/01/some_tips_for_using_javascript/#comments</comments><guid isPermaLink="false">http://www.planabc.net/?p=398</guid><dc:creator>怿飞</dc:creator><fs:srclink>http://www.planabc.net/2010/04/01/some_tips_for_using_javascript/</fs:srclink><fs:srcfeed>http://www.planabc.net/feed/</fs:srcfeed><fs:itemid>feedsky/planabc/~7049616/410553738/5157647</fs:itemid></item></channel></rss>