<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_汤姆大叔的博客</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/101461/rss</id><updated>2012-04-27T05:44:51Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/101461/rss"/><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/26/2443010.html</id><title type="text">深入理解JavaScript系列（48）：对象创建模式（下篇）</title><summary type="text">介绍本篇主要是介绍创建对象方面的模式的下篇，利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码。模式6：函数语法糖函数语法糖是为一个对象快速添加方法（函数）的扩展，这个主要是利用prototype的特性，代码比较简单，我们先来看一下实现代码：if (typeof Function.prototype.method !== "function") { Function.prototype.method = function (name, implementation) { this.prototype[name] = implementation; r...</summary><published>2012-04-26T00:46:00Z</published><updated>2012-04-26T00:46:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/26/2443010.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/26/2443010.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本篇主要是介绍创建对象方面的模式的下篇，利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式6：函数语法糖&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;函数语法糖是为一个对象快速添加方法（函数）的扩展，这个主要是利用prototype的特性，代码比较简单，我们先来看一下实现代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; Function.prototype.method !== "function"&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;    Function.prototype.method &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (name, implementation) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.prototype[name] =&lt;span style="color: #000000;"&gt; implementation;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;    };&lt;br/&gt;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;扩展对象的时候，可以这么用：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Person = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (name) {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name =&lt;span style="color: #000000;"&gt; name;&lt;br/&gt;}&lt;br/&gt;.method(&lt;/span&gt;'getName'&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.name;&lt;br/&gt;            })&lt;br/&gt;.method(&lt;/span&gt;'setName', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (name) {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name =&lt;span style="color: #000000;"&gt; name;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;});&lt;/span&gt;&lt;/div&gt;&lt;p&gt;这样就给Person函数添加了getName和setName这2个方法，接下来我们来验证一下结果：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; a = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Person('Adam'&lt;span style="color: #000000;"&gt;);&lt;br/&gt;console.log(a.getName()); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 'Adam'&lt;/span&gt;&lt;br/&gt;console.log(a.setName('Eve').getName()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 'Eve'&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;模式7：对象常量&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对象常量是在一个对象提供set,get,ifDefined各种方法的体现，而且对于set的方法只会保留最先设置的对象，后期再设置都是无效的，已达到别人无法重载的目的。实现代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; constant = (&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; constants =&lt;span style="color: #000000;"&gt; {},&lt;br/&gt;        ownProp &lt;/span&gt;=&lt;span style="color: #000000;"&gt; Object.prototype.hasOwnProperty,&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 只允许设置这三种类型的值&lt;/span&gt;&lt;br/&gt;        allowed =&lt;span style="color: #000000;"&gt; {&lt;br/&gt;            string: &lt;/span&gt;1&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            number: &lt;/span&gt;1&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;boolean&lt;/span&gt;: 1&lt;span style="color: #000000;"&gt;&lt;br/&gt;        },&lt;br/&gt;        prefix &lt;/span&gt;= (Math.random() + "_").slice(2&lt;span style="color: #000000;"&gt;);&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 设置名称为name的属性&lt;/span&gt;&lt;br/&gt;        set: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (name, value) {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.isDefined(name)) {&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;            }&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!ownProp.call(allowed, &lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt; value)) {&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;            }&lt;br/&gt;            constants[prefix &lt;/span&gt;+ name] =&lt;span style="color: #000000;"&gt; value;&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;        },&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 判断是否存在名称为name的属性&lt;/span&gt;&lt;br/&gt;        isDefined: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (name) {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; ownProp.call(constants, prefix +&lt;span style="color: #000000;"&gt; name);&lt;br/&gt;        },&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 获取名称为name的属性&lt;/span&gt;&lt;br/&gt;        get: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (name) {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.isDefined(name)) {&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; constants[prefix +&lt;span style="color: #000000;"&gt; name];&lt;br/&gt;            }&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;        }&lt;br/&gt;    };&lt;br/&gt;} ());&lt;/span&gt;&lt;/div&gt;&lt;p&gt;验证代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 检查是否存在&lt;/span&gt;&lt;br/&gt;console.log(constant.isDefined("maxwidth")); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; false&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 定义&lt;/span&gt;&lt;br/&gt;console.log(constant.set("maxwidth", 480)); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 重新检测&lt;/span&gt;&lt;br/&gt;console.log(constant.isDefined("maxwidth")); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 尝试重新定义&lt;/span&gt;&lt;br/&gt;console.log(constant.set("maxwidth", 320)); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; false&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 判断原先的定义是否还存在&lt;/span&gt;&lt;br/&gt;console.log(constant.get("maxwidth")); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 480&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;模式8：沙盒模式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;沙盒（Sandbox）模式即时为一个或多个模块提供单独的上下文环境，而不会影响其他模块的上下文环境，比如有个Sandbox里有3个方法event,dom,ajax，在调用其中2个组成一个环境的话，和调用三个组成的环境完全没有干扰。Sandbox实现代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; Sandbox() {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 将参数转为数组&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; args =&lt;span style="color: #000000;"&gt; Array.prototype.slice.call(arguments),&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 最后一个参数为callback&lt;/span&gt;&lt;br/&gt;        callback =&lt;span style="color: #000000;"&gt; args.pop(),&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 除最后一个参数外，其它均为要选择的模块&lt;/span&gt;&lt;br/&gt;        modules = (args[0] &amp;amp;&amp;amp; &lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; args[0] === "string") ? args : args[0&lt;span style="color: #000000;"&gt;],&lt;br/&gt;        i;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 强制使用new操作符&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;instanceof&lt;/span&gt;&lt;span style="color: #000000;"&gt; Sandbox)) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Sandbox(modules, callback);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 添加属性&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.a = 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.b = 2&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 向this对象上需想添加模块&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 如果没有模块或传入的参数为 "*" ，则以为着传入所有模块&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!modules || modules == '*'&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;        modules &lt;/span&gt;=&lt;span style="color: #000000;"&gt; [];&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (i &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt; Sandbox.modules) {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Sandbox.modules.hasOwnProperty(i)) {&lt;br/&gt;                modules.push(i);&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 初始化需要的模块&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; modules.length; i += 1&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;        Sandbox.modules[modules[i]](&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 调用 callback&lt;/span&gt;&lt;br/&gt;    callback(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 默认添加原型对象&lt;/span&gt;&lt;br/&gt;Sandbox.prototype =&lt;span style="color: #000000;"&gt; {&lt;br/&gt;    name: &lt;/span&gt;"My Application"&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    version: &lt;/span&gt;"1.0"&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    getName: &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.name;&lt;br/&gt;    }&lt;br/&gt;};&lt;/span&gt;&lt;/div&gt;&lt;p&gt;然后我们再定义默认的初始模块：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Sandbox.modules =&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;&lt;br/&gt;Sandbox.modules.dom &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box) {&lt;br/&gt;    box.getElement &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    };&lt;br/&gt;    box.getStyle &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    };&lt;br/&gt;    box.foo &lt;/span&gt;= "bar"&lt;span style="color: #000000;"&gt;;&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;Sandbox.modules.event &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box) {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; access to the Sandbox prototype if needed:&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; box.constructor.prototype.m = "mmm";&lt;/span&gt;&lt;br/&gt;    box.attachEvent = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    };&lt;br/&gt;    box.detachEvent &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    };&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;Sandbox.modules.ajax &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box) {&lt;br/&gt;    box.makeRequest &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    };&lt;br/&gt;    box.getResponse &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    };&lt;br/&gt;};&lt;/span&gt;&lt;/div&gt;&lt;p&gt;调用方式如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 调用方式&lt;/span&gt;&lt;br/&gt;Sandbox(['ajax', 'event'], &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box) {&lt;br/&gt;    console.log(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box.foo));&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 没有选择dom，所以box.foo不存在&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;});&lt;br/&gt;&lt;br/&gt;Sandbox(&lt;/span&gt;'ajax', 'dom', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box) {&lt;br/&gt;    console.log(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box.attachEvent));&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 没有选择event,所以event里定义的attachEvent也不存在&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;});&lt;br/&gt;&lt;br/&gt;Sandbox(&lt;/span&gt;'*', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (box) {&lt;br/&gt;    console.log(box); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 上面定义的所有方法都可访问&lt;/span&gt;&lt;br/&gt;});&lt;/div&gt;&lt;p&gt;通过三个不同的调用方式，我们可以看到，三种方式的上下文环境都是不同的，第一种里没有foo; 而第二种则没有attachEvent，因为只加载了ajax和dom，而没有加载event; 第三种则加载了全部。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式9：静态成员&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;静态成员（Static Members）只是一个函数或对象提供的静态属性，可分为私有的和公有的，就像C#或Java里的public static和private static一样。&lt;/p&gt;&lt;p&gt;我们先来看一下公有成员，公有成员非常简单，我们平时声明的方法，函数都是公有的，比如：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 构造函数&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Gadget = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 公有静态方法&lt;/span&gt;&lt;br/&gt;Gadget.isShiny = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; "you bet"&lt;span style="color: #000000;"&gt;;&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 原型上添加的正常方法&lt;/span&gt;&lt;br/&gt;Gadget.prototype.setPrice = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (price) {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.price =&lt;span style="color: #000000;"&gt; price;&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 调用静态方法&lt;/span&gt;&lt;br/&gt;console.log(Gadget.isShiny()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "you bet"&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建实例，然后调用方法&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; iphone = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Gadget();&lt;br/&gt;iphone.setPrice(&lt;/span&gt;500&lt;span style="color: #000000;"&gt;);&lt;br/&gt;&lt;br/&gt;console.log(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; Gadget.setPrice); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "undefined"&lt;/span&gt;&lt;br/&gt;console.log(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; iphone.isShiny); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "undefined"&lt;/span&gt;&lt;br/&gt;Gadget.prototype.isShiny =&lt;span style="color: #000000;"&gt; Gadget.isShiny;&lt;br/&gt;console.log(iphone.isShiny()); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "you bet"&lt;/span&gt;&lt;/div&gt;&lt;p&gt;而私有静态成员，我们可以利用其闭包特性去实现，以下是两种实现方式。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第一种实现方式：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Gadget = (&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 静态变量/属性&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; counter = 0&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 闭包返回构造函数的新实现&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;        console.log(counter &lt;/span&gt;+= 1&lt;span style="color: #000000;"&gt;);&lt;br/&gt;    };&lt;br/&gt;} ()); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 立即执行&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; g1 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Gadget(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; logs 1&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; g2 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Gadget(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; logs 2&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; g3 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Gadget(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; logs 3&lt;/span&gt;&lt;/div&gt;&lt;p&gt;可以看出，虽然每次都是new的对象，但数字依然是递增的，达到了静态成员的目的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第二种方式：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Gadget = (&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 静态变量/属性&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; counter = 0&lt;span style="color: #000000;"&gt;,&lt;br/&gt;        NewGadget;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;新构造函数实现&lt;/span&gt;&lt;br/&gt;    NewGadget = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;        counter &lt;/span&gt;+= 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;   };&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 授权可以访问的方法&lt;/span&gt;&lt;br/&gt;    NewGadget.prototype.getLastId = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; counter;&lt;br/&gt;    };&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 覆盖构造函数&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; NewGadget;&lt;br/&gt;} ()); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 立即执行&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; iphone = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Gadget();&lt;br/&gt;iphone.getLastId(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 1&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; ipod = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Gadget();&lt;br/&gt;ipod.getLastId(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 2&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; ipad = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Gadget();&lt;br/&gt;ipad.getLastId(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 3&lt;/span&gt;&lt;/div&gt;&lt;p&gt;数字也是递增了，这是利用其内部授权方法的闭包特性实现的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这是对象创建模式的下篇，两篇一起总共9种模式，是我们在日常JavaScript编程中经常使用的对象创建模式，不同的场景起到了不同的作用，希望大家根据各自的需求选择适用的模式。&lt;/p&gt;&lt;p&gt;参考：http://shichuan.github.com/javascript-patterns/#object-creation-patterns&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2443010.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/26/2443010.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/25/2439527.html</id><title type="text">深入理解JavaScript系列（47）：对象创建模式（上篇）</title><summary type="text">介绍本篇主要是介绍创建对象方面的模式，利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码。模式1：命名空间（namespace）命名空间可以减少全局命名所需的数量，避免命名冲突或过度。一般我们在进行对象层级定义的时候，经常是这样的：var app = app || {};app.moduleA = app.moduleA || {};app.moduleA.subModule = app.moduleA.subModule || {};app.moduleA.subModule.MethodA = function () { console.log("print A&amp;quo</summary><published>2012-04-25T00:49:00Z</published><updated>2012-04-25T00:49:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/25/2439527.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/25/2439527.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本篇主要是介绍创建对象方面的模式，利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式1：命名空间（namespace）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;命名空间可以减少全局命名所需的数量，避免命名冲突或过度。一般我们在进行对象层级定义的时候，经常是这样的：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; app = app ||&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;app.moduleA &lt;/span&gt;= app.moduleA ||&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;app.moduleA.subModule &lt;/span&gt;= app.moduleA.subModule ||&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;app.moduleA.subModule.MethodA &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    console.log(&lt;/span&gt;"print A"&lt;span style="color: #000000;"&gt;);&lt;br/&gt;};&lt;br/&gt;app.moduleA.subModule.MethodB &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    console.log(&lt;/span&gt;"print B"&lt;span style="color: #000000;"&gt;);&lt;br/&gt;};&lt;/span&gt;&lt;/div&gt;&lt;p&gt;如果层级很多的话，那就要一直这样继续下去，很是混乱。namespace模式就是为了解决这个问题而存在的，我们看代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 不安全，可能会覆盖已有的MYAPP对象&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; MYAPP =&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 还好&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; MYAPP === "undefined"&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; MYAPP =&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;}&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 更简洁的方式&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; MYAPP = MYAPP ||&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;定义通用方法&lt;/span&gt;&lt;br/&gt;MYAPP.namespace = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (ns_string) {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; parts = ns_string.split('.'&lt;span style="color: #000000;"&gt;),&lt;br/&gt;        parent &lt;/span&gt;=&lt;span style="color: #000000;"&gt; MYAPP,&lt;br/&gt;        i;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 默认如果第一个节点是MYAPP的话，就忽略掉，比如MYAPP.ModuleA&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (parts[0] === "MYAPP"&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;        parts &lt;/span&gt;= parts.slice(1&lt;span style="color: #000000;"&gt;);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; parts.length; i += 1&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 如果属性不存在，就创建&lt;/span&gt;&lt;br/&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; parent[parts[i]] === "undefined"&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;            parent[parts[i]] &lt;/span&gt;=&lt;span style="color: #000000;"&gt; {};&lt;br/&gt;        }&lt;br/&gt;        parent &lt;/span&gt;=&lt;span style="color: #000000;"&gt; parent[parts[i]];&lt;br/&gt;    }&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; parent;&lt;br/&gt;};&lt;/span&gt;&lt;/div&gt;&lt;p&gt;调用代码，非常简单：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 通过namespace以后，可以将返回值赋给一个局部变量&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; module2 = MYAPP.namespace('MYAPP.modules.module2'&lt;span style="color: #000000;"&gt;);&lt;br/&gt;console.log(module2 &lt;/span&gt;=== MYAPP.modules.module2); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 跳过MYAPP&lt;/span&gt;&lt;br/&gt;MYAPP.namespace('modules.module51'&lt;span style="color: #000000;"&gt;);&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 非常长的名字&lt;/span&gt;&lt;br/&gt;MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');&lt;/div&gt;&lt;p&gt;&lt;strong&gt;模式2：定义依赖&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;有时候你的一个模块或者函数可能要引用第三方的一些模块或者工具，这时候最好将这些依赖模块在刚开始的时候就定义好，以便以后可以很方便地替换掉。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; myFunction = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 依赖模块&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; event =&lt;span style="color: #000000;"&gt; YAHOO.util.Event,&lt;br/&gt;        dom &lt;/span&gt;=&lt;span style="color: #000000;"&gt; YAHOO.util.dom;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 其它函数后面的代码里使用局部变量event和dom&lt;/span&gt;&lt;br/&gt;};&lt;/div&gt;&lt;p&gt;&lt;strong&gt;模式3：私有属性和私有方法&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;JavaScript本书不提供特定的语法来支持私有属性和私有方法，但是我们可以通过闭包来实现，代码如下：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; Gadget() {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 私有对象&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; name = 'iPod'&lt;span style="color: #000000;"&gt;;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 公有函数&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.getName = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; name;&lt;br/&gt;    };&lt;br/&gt;}&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; toy = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Gadget();&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; name未定义，是私有的&lt;/span&gt;&lt;br/&gt;console.log(toy.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; undefined&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 公有方法访问name&lt;/span&gt;&lt;br/&gt;console.log(toy.getName()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "iPod"&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; myobj; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 通过自执行函数给myobj赋值&lt;/span&gt;&lt;br/&gt;(&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 自由对象&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; name = "my, oh my"&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 实现了公有部分，所以没有var&lt;/span&gt;&lt;br/&gt;    myobj =&lt;span style="color: #000000;"&gt; {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 授权方法&lt;/span&gt;&lt;br/&gt;        getName: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; name;&lt;br/&gt;        }&lt;br/&gt;    };&lt;br/&gt;} ());&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;模式4：Revelation模式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;也是关于隐藏私有方法的模式，和《&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/30/2288372.html" target="_blank"&gt;深入理解JavaScript系列（3）：全面解析Module模式&lt;/a&gt;》里的Module模式有点类似，但是不是return的方式，而是在外部先声明一个变量，然后在内部给变量赋值公有方法。代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="color: #000000;"&gt; myarray;&lt;br/&gt;&lt;br/&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; astr = "[object Array]"&lt;span style="color: #000000;"&gt;,&lt;br/&gt;        toString &lt;/span&gt;=&lt;span style="color: #000000;"&gt; Object.prototype.toString;&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; isArray(a) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; toString.call(a) ===&lt;span style="color: #000000;"&gt; astr;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; indexOf(haystack, needle) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; i = 0&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            max &lt;/span&gt;=&lt;span style="color: #000000;"&gt; haystack.length;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (; i &amp;lt; max; i += 1&lt;span style="color: #000000;"&gt;) {&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (haystack[i] ===&lt;span style="color: #000000;"&gt; needle) {&lt;br/&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; i;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; -1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过赋值的方式，将上面所有的细节都隐藏了&lt;/span&gt;&lt;br/&gt;    myarray =&lt;span style="color: #000000;"&gt; {&lt;br/&gt;        isArray: isArray,&lt;br/&gt;        indexOf: indexOf,&lt;br/&gt;        inArray: indexOf&lt;br/&gt;    };&lt;br/&gt;} ());&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;测试代码&lt;/span&gt;&lt;br/&gt;console.log(myarray.isArray([1, 2])); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;br/&gt;console.log(myarray.isArray({ 0: 1 })); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; false&lt;/span&gt;&lt;br/&gt;console.log(myarray.indexOf(["a", "b", "z"], "z")); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 2&lt;/span&gt;&lt;br/&gt;console.log(myarray.inArray(["a", "b", "z"], "z")); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 2&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;myarray.indexOf &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;console.log(myarray.inArray([&lt;/span&gt;"a", "b", "z"], "z")); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 2&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;模式5：链模式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;链模式可以你连续可以调用一个对象的方法，比如obj.add(1).remove(2).delete(4).add(2)这样的形式，其实现思路非常简单，就是将this原样返回。代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; obj =&lt;span style="color: #000000;"&gt; {&lt;br/&gt;    value: &lt;/span&gt;1&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    increment: &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.value += 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;    },&lt;br/&gt;    add: &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; (v) {&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.value +=&lt;span style="color: #000000;"&gt; v;&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;    },&lt;br/&gt;    shout: &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; () {&lt;br/&gt;        console.log(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.value);&lt;br/&gt;    }&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 链方法调用&lt;/span&gt;&lt;br/&gt;obj.increment().add(3).shout(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 5&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 也可以单独一个一个调用&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;obj.increment();&lt;br/&gt;obj.add(&lt;/span&gt;3&lt;span style="color: #000000;"&gt;);&lt;br/&gt;obj.shout();&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本篇是对象创建模式的上篇，敬请期待明天的下篇。&lt;/p&gt;&lt;p&gt;参考：http://shichuan.github.com/javascript-patterns/#object-creation-patterns&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2439527.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/25/2439527.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/24/2438050.html</id><title type="text">深入理解JavaScript系列（46）：代码复用模式（推荐篇）</title><summary type="text">介绍本文介绍的四种代码复用模式都是最佳实践，推荐大家在编程的过程中使用。模式1：原型继承原型继承是让父对象作为子对象的原型，从而达到继承的目的：function object(o) { function F() { } F.prototype = o; return new F();}// 要继承的父对象var parent = { name: "Papa"};// 新对象var child = object(parent);// 测试console.log(child.name); // "Papa"// 父构造函数function Person() </summary><published>2012-04-24T00:38:00Z</published><updated>2012-04-24T00:38:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/24/2438050.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/24/2438050.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文介绍的四种代码复用模式都是最佳实践，推荐大家在编程的过程中使用。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式1：原型继承&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;原型继承是让父对象作为子对象的原型，从而达到继承的目的：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; object(o) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; F() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    F.prototype = o;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; F();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 要继承的父对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; parent = {&lt;br /&gt;    name: "Papa"&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 新对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; child = object(parent);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 测试&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(child.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Papa"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 父构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Person() {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; an "own" property&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = "Adam";&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给原型添加新属性&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Person.prototype.getName = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建新person&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; papa = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Person();&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 继承&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = object(papa);&lt;br /&gt;console.log(kid.getName()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Adam"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 父构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Person() {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; an "own" property&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = "Adam";&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给原型添加新属性&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Person.prototype.getName = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 继承&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = object(Person.prototype);&lt;br /&gt;console.log(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; kid.getName); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "function",因为是在原型里定义的&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; kid.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "undefined", 因为只继承了原型&lt;/span&gt;&lt;/div&gt;&lt;p&gt;同时，ECMAScript5也提供了类似的一个方法叫做Object.create用于继承对象，用法如下：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; 使用新版的ECMAScript 5提供的功能 &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; child = Object.create(parent);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; child = Object.create(parent, {&lt;br /&gt;    age: { value: 2} &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ECMA5 descriptor&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;});&lt;br /&gt;console.log(child.hasOwnProperty("age")); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;/div&gt;&lt;p&gt;而且，也可以更细粒度地在第二个参数上定义属性：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 首先，定义一个新对象man&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; man = Object.create(&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 接着，创建包含属性的配置设置&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 属性设置为可写，可枚举，可配置&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; config = {&lt;br /&gt;    writable: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;,&lt;br /&gt;    enumerable: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;,&lt;br /&gt;    configurable: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 通常使用Object.defineProperty()来添加新属性(ECMAScript5支持）&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 现在，为了方便，我们自定义一个封装函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; defineProp = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (obj, key, value) {&lt;br /&gt;    config.value = value;&lt;br /&gt;    Object.defineProperty(obj, key, config);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;defineProp(man, 'car', 'Delorean');&lt;br /&gt;defineProp(man, 'dob', '1981');&lt;br /&gt;defineProp(man, 'beard', &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;);&lt;/div&gt;&lt;p&gt;所以，继承就这么可以做了：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; driver = Object.create( man );&lt;br /&gt;defineProp (driver, 'topSpeed', '100mph');&lt;br /&gt;driver.topSpeed &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 100mph&lt;/span&gt;&lt;/div&gt;&lt;p&gt;但是有个地方需要注意，就是&lt;span style="color: #ff6600;"&gt;Object.create(null)&lt;/span&gt;创建的对象的原型为&lt;span style="color: #ff6600;"&gt;undefined&lt;/span&gt;，也就是没有&lt;span style="color: #ff6600;"&gt;toString&lt;/span&gt;和&lt;span style="color: #ff6600;"&gt;valueOf&lt;/span&gt;方法，所以&lt;span style="color: #ff6600;"&gt;alert(man);&lt;/span&gt;的时候会出错，但&lt;span style="color: #ff6600;"&gt;alert(man.car);&lt;/span&gt;是没问题的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式2：复制所有属性进行继承&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这种方式的继承就是将父对象里所有的属性都复制到子对象上，一般子对象可以使用父对象的数据。&lt;/p&gt;&lt;p&gt;先来看一个浅拷贝的例子：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; 浅拷贝 &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; extend(parent, child) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; i;&lt;br /&gt;    child = child || {};&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (i &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; parent) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (parent.hasOwnProperty(i)) {&lt;br /&gt;            child[i] = parent[i];&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; child;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; dad = { name: "Adam" };&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = extend(dad);&lt;br /&gt;console.log(kid.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Adam"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; dad = {&lt;br /&gt;    counts: [1, 2, 3],&lt;br /&gt;    reads: { paper: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = extend(dad);&lt;br /&gt;kid.counts.push(4);&lt;br /&gt;console.log(dad.counts.toString()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "1,2,3,4"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(dad.reads === kid.reads); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;/div&gt;&lt;p&gt;代码的最后一行，你可以发现dad和kid的reads是一样的，也就是他们使用的是同一个引用，这也就是浅拷贝带来的问题。&lt;/p&gt;&lt;p&gt;我们再来看一下深拷贝：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; 深拷贝 &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; extendDeep(parent, child) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; i,&lt;br /&gt;        toStr = Object.prototype.toString,&lt;br /&gt;        astr = "[object Array]";&lt;br /&gt;&lt;br /&gt;    child = child || {};&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (i &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; parent) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (parent.hasOwnProperty(i)) {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; parent[i] === 'object') {&lt;br /&gt;                child[i] = (toStr.call(parent[i]) === astr) ? [] : {};&lt;br /&gt;                extendDeep(parent[i], child[i]);&lt;br /&gt;            } &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; {&lt;br /&gt;                child[i] = parent[i];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; child;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; dad = {&lt;br /&gt;    counts: [1, 2, 3],&lt;br /&gt;    reads: { paper: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = extendDeep(dad);&lt;br /&gt;&lt;br /&gt;kid.counts.push(4);&lt;br /&gt;console.log(kid.counts.toString()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "1,2,3,4"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(dad.counts.toString()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "1,2,3"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;console.log(dad.reads === kid.reads); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; false&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;kid.reads.paper = &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;;&lt;/div&gt;&lt;p&gt;深拷贝以后，两个值就不相等了，bingo！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式3：混合（mix-in）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;混入就是将一个对象的一个或多个（或全部）属性（或方法）复制到另外一个对象，我们举一个例子：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; mix() {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; arg, prop, child = {};&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (arg = 0; arg &amp;lt; arguments.length; arg += 1) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (prop &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; arguments[arg]) {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (arguments[arg].hasOwnProperty(prop)) {&lt;br /&gt;                child[prop] = arguments[arg][prop];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; child;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; cake = mix(&lt;br /&gt;                { eggs: 2, large: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt; },&lt;br /&gt;                { butter: 1, salted: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt; },&lt;br /&gt;                { flour: '3 cups' },&lt;br /&gt;                { sugar: 'sure!' }&lt;br /&gt;                );&lt;br /&gt;&lt;br /&gt;console.dir(cake);&lt;/div&gt;&lt;p&gt;mix函数将所传入的所有参数的子属性都复制到child对象里，以便产生一个新对象。&lt;/p&gt;&lt;p&gt;那如何我们只想混入部分属性呢？该个如何做？其实我们可以使用多余的参数来定义需要混入的属性，例如mix（child,parent,method1,method2)这样就可以只将parent里的method1和method2混入到child里。上代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Car &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Car = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (settings) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.model = settings.model || 'no model provided';&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.colour = settings.colour || 'no colour provided';&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Mixin&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Mixin = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () { };&lt;br /&gt;Mixin.prototype = {&lt;br /&gt;    driveForward: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        console.log('drive forward');&lt;br /&gt;    },&lt;br /&gt;    driveBackward: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        console.log('drive backward');&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 定义的2个参数分别是被混入的对象（reciving）和从哪里混入的对象（giving)&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; augment(receivingObj, givingObj) {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 如果提供了指定的方法名称的话，也就是参数多余3个&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (arguments[2]) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; i = 2, len = arguments.length; i &amp;lt; len; i++) {&lt;br /&gt;            receivingObj.prototype[arguments[i]] = givingObj.prototype[arguments[i]];&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 如果不指定第3个参数，或者更多参数，就混入所有的方法&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; methodName &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; givingObj.prototype) {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 检查receiving对象内部不包含要混入的名字，如何包含就不混入了&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!receivingObj.prototype[methodName]) {&lt;br /&gt;                receivingObj.prototype[methodName] = givingObj.prototype[methodName];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给Car混入属性，但是值混入'driveForward' 和 'driveBackward'*/&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;augment(Car, Mixin, 'driveForward', 'driveBackward');&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建新对象Car&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; vehicle = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Car({ model: 'Ford Escort', colour: 'blue' });&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 测试是否成功得到混入的方法&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;vehicle.driveForward();&lt;br /&gt;vehicle.driveBackward();&lt;/div&gt;&lt;p&gt;该方法使用起来就比较灵活了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式4：借用方法&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;一个对象借用另外一个对象的一个或两个方法，而这两个对象之间不会有什么直接联系。不用多解释，直接用代码解释吧：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; one = {&lt;br /&gt;    name: 'object',&lt;br /&gt;    say: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (greet) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; greet + ', ' + &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 测试&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(one.say('hi')); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "hi, object"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; two = {&lt;br /&gt;    name: 'another object'&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;console.log(one.say.apply(two, ['hello'])); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "hello, another object"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 将say赋值给一个变量，this将指向到全局变量&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; say = one.say;&lt;br /&gt;console.log(say('hoho')); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "hoho, undefined"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 传入一个回调函数callback&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; yetanother = {&lt;br /&gt;    name: 'Yet another object',&lt;br /&gt;    method: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (callback) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; callback('Hola');&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;console.log(yetanother.method(one.say)); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Holla, undefined"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; bind(o, m) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; m.apply(o, [].slice.call(arguments));&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; twosay = bind(two, one.say);&lt;br /&gt;console.log(twosay('yo')); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "yo, another object"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ECMAScript 5给Function.prototype添加了一个bind()方法，以便很容易使用apply()和call()。&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; Function.prototype.bind === 'undefined') {&lt;br /&gt;    Function.prototype.bind = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (thisArg) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; fn = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;,&lt;br /&gt;slice = Array.prototype.slice,&lt;br /&gt;args = slice.call(arguments, 1);&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; fn.apply(thisArg, args.concat(slice.call(arguments)));&lt;br /&gt;        };&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; twosay2 = one.say.bind(two);&lt;br /&gt;console.log(twosay2('Bonjour')); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Bonjour, another object"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; twosay3 = one.say.bind(two, 'Enchant&amp;eacute;');&lt;br /&gt;console.log(twosay3()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Enchant&amp;eacute;, another object"&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&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;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2438050.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/24/2438050.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/23/2438005.html</id><title type="text">深入理解JavaScript系列（45）：代码复用模式（避免篇）</title><summary type="text">介绍任何编程都提出代码复用，否则话每次开发一个新程序或者写一个新功能都要全新编写的话，那就歇菜了，但是代码复用也是有好要坏，接下来的两篇文章我们将针对代码复用来进行讨论，第一篇文避免篇，指的是要尽量避免使用这些模式，因为或多或少有带来一些问题；第二排是推荐篇，指的是推荐大家使用的模式，一般不会有什么问题。模式1：默认模式代码复用大家常用的默认模式，往往是有问题的，该模式使用Parent()的构造函数创建一个对象，并且将该对象赋值给Child()的原型。我们看一下代码：function inherit(C, P) { C.prototype = new P();}// 父构造函数funct...</summary><published>2012-04-23T00:02:00Z</published><updated>2012-04-23T00:02:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/23/2438005.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/23/2438005.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;任何编程都提出代码复用，否则话每次开发一个新程序或者写一个新功能都要全新编写的话，那就歇菜了，但是代码复用也是有好要坏，接下来的两篇文章我们将针对代码复用来进行讨论，第一篇文避免篇，指的是要尽量避免使用这些模式，因为或多或少有带来一些问题；第二排是推荐篇，指的是推荐大家使用的模式，一般不会有什么问题。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式1：默认模式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;代码复用大家常用的默认模式，往往是有问题的，该模式使用Parent()的构造函数创建一个对象，并且将该对象赋值给Child()的原型。我们看一下代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; inherit(C, P) {&lt;br /&gt;    C.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; P();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 父构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Parent(name) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = name || 'Adam';&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给原型添加say功能&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Parent.prototype.say = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Child构造函数为空&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Child(name) {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 执行继承&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;inherit(Child, Parent);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child();&lt;br /&gt;console.log(kid.say()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Adam"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kiddo = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child();&lt;br /&gt;kiddo.name = "Patrick";&lt;br /&gt;console.log(kiddo.say()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Patrick"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 缺点:不能让参数传进给Child构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; s = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child('Seth');&lt;br /&gt;console.log(s.say()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Adam"&lt;/span&gt;&lt;/div&gt;&lt;p&gt;这种模式的缺点是Child不能传进参数，基本上也就废了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式2：借用构造函数&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;该模式是Child借用Parent的构造函数进行apply，然后将child的this和参数传递给apply方法：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 父构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Parent(name) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = name || 'Adam';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给原型添加say功能&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Parent.prototype.say = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Child构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Child(name) {&lt;br /&gt;    Parent.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, arguments);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child("Patrick");&lt;br /&gt;console.log(kid.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Patrick"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 缺点：没有从构造函数上继承say方法&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; kid.say); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "undefined"&lt;/span&gt;&lt;/div&gt;&lt;p&gt;缺点也很明显，say方法不可用，因为没有继承过来。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式3：借用构造函数并设置原型&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;上述两个模式都有自己的缺点，那如何把两者的缺点去除呢，我们来尝试一下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 父构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Parent(name) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = name || 'Adam';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给原型添加say功能&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Parent.prototype.say = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Child构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Child(name) {&lt;br /&gt;    Parent.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, arguments);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Child.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Parent();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child("Patrick");&lt;br /&gt;console.log(kid.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Patrick"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; kid.say); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; function&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(kid.say()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Patrick&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.dir(kid);&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;delete&lt;/span&gt; kid.name;&lt;br /&gt;console.log(kid.say()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Adam"&lt;/span&gt;&lt;/div&gt;&lt;p&gt;运行起来，一切正常，但是有没有发现，Parent构造函数执行了两次，所以说，虽然程序可用，但是效率很低。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式4：共享原型&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;共享原型是指Child和Parent使用同样的原型，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; inherit(C, P) {&lt;br /&gt;    C.prototype = P.prototype;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 父构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Parent(name) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = name || 'Adam';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给原型添加say功能&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Parent.prototype.say = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Child构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Child(name) {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;inherit(Child, Parent);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child('Patrick');&lt;br /&gt;console.log(kid.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; undefined&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; kid.say); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; function&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;kid.name = 'Patrick';&lt;br /&gt;console.log(kid.say()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Patrick&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.dir(kid);&lt;/div&gt;&lt;p&gt;确定还是一样，Child的参数没有正确接收到。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式5：临时构造函数&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;首先借用构造函数，然后将Child的原型设置为该借用构造函数的实例，最后恢复Child原型的构造函数。代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; 闭包 &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; inherit = (&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; F = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    };&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (C, P) {&lt;br /&gt;        F.prototype = P.prototype;&lt;br /&gt;        C.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; F();&lt;br /&gt;        C.uber = P.prototype;&lt;br /&gt;        C.prototype.constructor = C;&lt;br /&gt;    }&lt;br /&gt;} ());&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Parent(name) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = name || 'Adam';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 给原型添加say功能&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Parent.prototype.say = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Child构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; Child(name) {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;inherit(Child, Parent);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child();&lt;br /&gt;console.log(kid.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; undefined&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt; kid.say); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; function&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;kid.name = 'Patrick';&lt;br /&gt;console.log(kid.say()); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Patrick&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; kid2 = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Child("Tom");&lt;br /&gt;console.log(kid.say()); &lt;br /&gt;console.log(kid.constructor.name); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Child&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(kid.constructor === Parent); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; false&lt;/span&gt;&lt;/div&gt;&lt;p&gt;问题照旧，Child不能正常接收参数。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模式6：klass&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个模式，先上代码吧：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; klass = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (Parent, props) {&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Child, F, i;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 1.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 新构造函数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    Child = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (Child.uber &amp;amp;&amp;amp; Child.uber.hasOwnProperty("__construct")) {&lt;br /&gt;            Child.uber.__construct.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, arguments);&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (Child.prototype.hasOwnProperty("__construct")) {&lt;br /&gt;            Child.prototype.__construct.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;, arguments);&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 2.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 继承&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    Parent = Parent || Object;&lt;br /&gt;    F = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    };&lt;br /&gt;    F.prototype = Parent.prototype;&lt;br /&gt;    Child.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; F();&lt;br /&gt;    Child.uber = Parent.prototype;&lt;br /&gt;    Child.prototype.constructor = Child;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 3.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 添加实现方法&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (i &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; props) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (props.hasOwnProperty(i)) {&lt;br /&gt;            Child.prototype[i] = props[i];&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; return the "class"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Child;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Man = klass(&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;, {&lt;br /&gt;    __construct: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (what) {&lt;br /&gt;        console.log("Man's constructor");&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name = what;&lt;br /&gt;    },&lt;br /&gt;    getName: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.name;&lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; first = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Man('Adam'); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; logs "Man's constructor"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;first.getName(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "Adam"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; SuperMan = klass(Man, {&lt;br /&gt;    __construct: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (what) {&lt;br /&gt;        console.log("SuperMan's constructor");&lt;br /&gt;    },&lt;br /&gt;    getName: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; name = SuperMan.uber.getName.call(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; "I am " + name;&lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; clark = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SuperMan('Clark Kent');&lt;br /&gt;clark.getName(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "I am Clark Kent"&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;console.log(clark &lt;span style="color: #0000ff;"&gt;instanceof&lt;/span&gt; Man); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log(clark &lt;span style="color: #0000ff;"&gt;instanceof&lt;/span&gt; SuperMan); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; true&lt;/span&gt;&lt;/div&gt;&lt;p&gt;怎么样？看着是不是有点晕，说好点，该模式的语法和规范拧得和别的语言一样，你愿意用么？咳。。。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;以上六个模式虽然在某种特殊情况下实现了某些功能，但是都存在各自的缺点，所以一般情况，大家要避免使用。&lt;/p&gt;&lt;p&gt;参考：http://shichuan.github.com/javascript-patterns/#code-reuse-patterns&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2438005.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/23/2438005.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/19/2437321.html</id><title type="text">深入理解JavaScript系列（44）：设计模式之桥接模式</title><summary type="text">介绍桥接模式（Bridge）将抽象部分与它的实现部分分离，使它们都可以独立地变化。正文桥接模式最常用在事件监控上，先看一段代码：addEvent(element, 'click', getBeerById);function getBeerById(e) {var id = this.id;asyncRequest('GET', 'beer.uri?id=' + id, function(resp) {// Callback response.console.log('Requested Beer: ' + resp.respon</summary><published>2012-04-18T23:08:00Z</published><updated>2012-04-18T23:08:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/19/2437321.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/19/2437321.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;桥接模式（Bridge）将抽象部分与它的实现部分分离，使它们都可以独立地变化。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;正文&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;桥接模式最常用在事件监控上，先看一段代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;addEvent(element, 'click', getBeerById);&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; getBeerById(e) {&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; id = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.id;&lt;br /&gt;asyncRequest('GET', 'beer.uri?id=' + id, &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(resp) {&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Callback response.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;console.log('Requested Beer: ' + resp.responseText);&lt;br /&gt;});&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;上述代码，有个问题就是getBeerById必须要有浏览器的上下文才能使用，因为其内部使用了this.id这个属性，如果没用上下文，那就歇菜了。所以说一般稍微有经验的程序员都会将程序改造成如下形式：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; getBeerById(id, callback) {&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 通过ID发送请求，然后返回数据&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;asyncRequest('GET', 'beer.uri?id=' + id, &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(resp) {&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; callback response&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;callback(resp.responseText);&lt;br /&gt;});&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;实用多了，对吧？首先ID可以随意传入，而且还提供了一个callback函数用于自定义处理函数。但是这个和桥接有什么关系呢？这就是下段代码所要体现的了：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;addEvent(element, 'click', getBeerByIdBridge);&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; getBeerByIdBridge (e) {&lt;br /&gt;getBeerById(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.id, &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(beer) {&lt;br /&gt;console.log('Requested Beer: '+beer);&lt;br /&gt;});&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;这里的getBeerByIdBridge就是我们定义的桥，用于将抽象的click事件和getBeerById连接起来，同时将事件源的ID，以及自定义的call函数（console.log输出）作为参数传入到getBeerById函数里。&lt;/p&gt;&lt;p&gt;这个例子看起来有些简单，我们再来一个复杂点的实战例子。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;实战XHR连接队列&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们要构建一个队列，队列里存放了很多ajax请求，使用队列（queue）主要是因为要确保先加入的请求先被处理。任何时候，我们可以暂停请求、删除请求、重试请求以及支持对各个请求的订阅事件。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;基础核心函数&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在正式开始之前，我们先定义一下核心的几个封装函数，首先第一个是异步请求的函数封装：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; asyncRequest = (&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; handleReadyState(o, callback) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; poll = window.setInterval(&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (o &amp;amp;&amp;amp; o.readyState == 4) {&lt;br /&gt;                            window.clearInterval(poll);&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (callback) {&lt;br /&gt;                                callback(o);&lt;br /&gt;                            }&lt;br /&gt;                        }&lt;br /&gt;                    },&lt;br /&gt;                    50&lt;br /&gt;                    );&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; getXHR = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; http;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;try&lt;/span&gt; {&lt;br /&gt;            http = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XMLHttpRequest;&lt;br /&gt;            getXHR = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XMLHttpRequest;&lt;br /&gt;            };&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;catch&lt;/span&gt; (e) {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; msxml = [&lt;br /&gt;                        'MSXML2.XMLHTTP.3.0',&lt;br /&gt;                        'MSXML2.XMLHTTP',&lt;br /&gt;                        'Microsoft.XMLHTTP'&lt;br /&gt;                        ];&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; i = 0, len = msxml.length; i &amp;lt; len; ++i) {&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;try&lt;/span&gt; {&lt;br /&gt;                    http = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ActiveXObject(msxml[i]);&lt;br /&gt;                    getXHR = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ActiveXObject(msxml[i]);&lt;br /&gt;                    };&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;catch&lt;/span&gt; (e) { }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; http;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (method, uri, callback, postData) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; http = getXHR();&lt;br /&gt;        http.open(method, uri, &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;);&lt;br /&gt;        handleReadyState(http, callback);&lt;br /&gt;        http.send(postData || &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;);&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; http;&lt;br /&gt;    };&lt;br /&gt;})();&lt;/div&gt;&lt;p&gt;上述封装的自执行函数是一个通用的Ajax请求函数，相信属性Ajax的人都能看懂了。&lt;/p&gt;&lt;p&gt;接下来我们定义一个通用的添加方法（函数）的方法：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Function.prototype.method = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (name, fn) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.prototype[name] = fn;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;;&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;最后再添加关于数组的2个方法，一个用于遍历，一个用于筛选：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!Array.prototype.forEach) {&lt;br /&gt;    Array.method('forEach', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (fn, thisObj) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; scope = thisObj || window;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; i = 0, len = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.length; i &amp;lt; len; ++i) {&lt;br /&gt;            fn.call(scope, &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;[i], i, &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!Array.prototype.filter) {&lt;br /&gt;    Array.method('filter', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (fn, thisObj) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; scope = thisObj || window;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; a = [];&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; i = 0, len = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.length; i &amp;lt; len; ++i) {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!fn.call(scope, &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;[i], i, &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;)) {&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;continue&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;            a.push(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;[i]);&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; a;&lt;br /&gt;    });&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;因为有的新型浏览器已经支持了这两种功能（或者有些类库已经支持了），所以要先判断，如果已经支持的话，就不再处理了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;观察者系统&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;观察者在队列里的事件过程中扮演着重要的角色，可以队列处理时（成功、失败、挂起）订阅事件：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;window.DED = window.DED || {};&lt;br /&gt;DED.util = DED.util || {};&lt;br /&gt;DED.util.Observer = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.fns = [];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;DED.util.Observer.prototype = {&lt;br /&gt;    subscribe: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (fn) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.fns.push(fn);&lt;br /&gt;    },&lt;br /&gt;&lt;br /&gt;    unsubscribe: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (fn) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.fns = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.fns.filter(&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (el) {&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (el !== fn) {&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; el;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            );&lt;br /&gt;            },&lt;br /&gt;    fire: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (o) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.fns.forEach(&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (el) {&lt;br /&gt;                el(o);&lt;br /&gt;            }&lt;br /&gt;            );&lt;br /&gt;    }&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;&lt;strong&gt;队列主要实现代码&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;首先订阅了队列的主要属性和事件委托：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;DED.Queue = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 包含请求的队列.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue = [];&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 使用Observable对象在3个不同的状态上，以便可以随时订阅事件&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.onComplete = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DED.util.Observer;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.onFailure = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DED.util.Observer;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.onFlush = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DED.util.Observer;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 核心属性，可以在外部调用的时候进行设置&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.retryCount = 3;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.currentRetry = 0;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.paused = &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.timeout = 5000;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.conn = {};&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.timer = {};&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;然后通过DED.Queue.method的链式调用，则队列上添加了很多可用的方法：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;DED.Queue.&lt;br /&gt;    method('flush', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; flush方法&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue.length &amp;gt; 0) {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.paused) {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.paused = &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; that = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.currentRetry++;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; abort = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;            that.conn.abort();&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (that.currentRetry == that.retryCount) {&lt;br /&gt;                that.onFailure.fire();&lt;br /&gt;                that.currentRetry = 0;&lt;br /&gt;            } &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; {&lt;br /&gt;                that.flush();&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.timer = window.setTimeout(abort, &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.timeout);&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; callback = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (o) {&lt;br /&gt;            window.clearTimeout(that.timer);&lt;br /&gt;            that.currentRetry = 0;&lt;br /&gt;            that.queue.shift();&lt;br /&gt;            that.onFlush.fire(o.responseText);&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (that.queue.length == 0) {&lt;br /&gt;                that.onComplete.fire();&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; recursive call to flush&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; that.flush();&lt;br /&gt;&lt;br /&gt;        };&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.conn = asyncRequest(&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue[0]['method'],&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue[0]['uri'],&lt;br /&gt;            callback,&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue[0]['params']&lt;br /&gt;            );&lt;br /&gt;    }).&lt;br /&gt;    method('setRetryCount', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (count) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.retryCount = count;&lt;br /&gt;    }).&lt;br /&gt;    method('setTimeout', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (time) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.timeout = time;&lt;br /&gt;    }).&lt;br /&gt;    method('add', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (o) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue.push(o);&lt;br /&gt;    }).&lt;br /&gt;    method('pause', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.paused = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;;&lt;br /&gt;    }).&lt;br /&gt;    method('dequeue', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue.pop();&lt;br /&gt;    }).&lt;br /&gt;    method('clear', &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.queue = [];&lt;br /&gt;    });&lt;/div&gt;&lt;p&gt;代码看起来很多，折叠以后就可以发现，其实就是在队列上定义了flush, setRetryCount, setTimeout, add, pause, dequeue, 和clear方法。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;简单调用&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; q = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DED.Queue;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 设置重试次数高一点，以便应付慢的连接&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.setRetryCount(5);&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 设置timeout时间&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.setTimeout(1000);&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 添加2个请求.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.add({&lt;br /&gt;    method: 'GET',&lt;br /&gt;    uri: '/path/to/file.php?ajax=true'&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;q.add({&lt;br /&gt;    method: 'GET',&lt;br /&gt;    uri: '/path/to/file.php?ajax=true&amp;amp;woe=me'&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; flush队列&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.flush();&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 暂停队列，剩余的保存&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.pause();&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 清空.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.clear();&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 添加2个请求.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.add({&lt;br /&gt;    method: 'GET',&lt;br /&gt;    uri: '/path/to/file.php?ajax=true'&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;q.add({&lt;br /&gt;    method: 'GET',&lt;br /&gt;    uri: '/path/to/file.php?ajax=true&amp;amp;woe=me'&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 从队列里删除最后一个请求.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.dequeue();&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 再次Flush&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;q.flush();&lt;/div&gt;&lt;p&gt;&lt;strong&gt;桥接呢？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;上面的调用代码里并没有桥接，那桥呢？看一下下面的完整示例，就可以发现处处都有桥哦：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;!&lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"&lt;br /&gt;"http://www.w3.org/TR/html4/strict.dtd"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;meta &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;http-equiv&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Content-type"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; content&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/html; charset=utf-8"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Ajax Connection Queue&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="utils.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="queue.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;        addEvent(window, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;load&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () {&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt; 实现.&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; q &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; DED.Queue;&lt;br /&gt;            q.setRetryCount(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;5&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br /&gt;            q.setTimeout(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;3000&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; items &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;items&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; results &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;results&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; queue &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;queue-items&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt; 在客户端保存跟踪自己的请求&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; requests &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; [];&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt; 每个请求flush以后，订阅特殊的处理步骤&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;            q.onFlush.subscribe(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (data) {&lt;br /&gt;                results.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; data;&lt;br /&gt;                requests.shift();&lt;br /&gt;                queue.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; requests.toString();&lt;br /&gt;            });&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt; 订阅时间处理步骤&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;            q.onFailure.subscribe(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () {&lt;br /&gt;                results.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;+=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &amp;lt;span style="color:red;"&amp;gt;Connection Error!&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;            });&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt; 订阅全部成功的处理步骤x&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;            q.onComplete.subscribe(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () {&lt;br /&gt;                results.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;+=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &amp;lt;span style="color:green;"&amp;gt;Completed!&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;            });&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; actionDispatcher &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (element) {&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (element) {&lt;br /&gt;                    &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;case&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;flush&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;br /&gt;                        q.flush();&lt;br /&gt;                        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;case&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;dequeue&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;br /&gt;                        q.dequeue();&lt;br /&gt;                        requests.pop();&lt;br /&gt;                        queue.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; requests.toString();&lt;br /&gt;                        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;case&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;pause&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;br /&gt;                        q.pause();&lt;br /&gt;                        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;case&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;clear&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;br /&gt;                        q.clear();&lt;br /&gt;                        requests &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; [];&lt;br /&gt;                        queue.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;''&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;                        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;                }&lt;br /&gt;            };&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; addRequest &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (request) {&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; data &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; request.split(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;-&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;)[&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;1&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;];&lt;br /&gt;                q.add({&lt;br /&gt;                    method: &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;GET&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;,&lt;br /&gt;                    uri: &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;bridge-connection-queue.php?ajax=true&amp;amp;s=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #000000;"&gt;+&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; data,&lt;br /&gt;                    params: &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;                });&lt;br /&gt;                requests.push(data);&lt;br /&gt;                queue.innerHTML &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; requests.toString();&lt;br /&gt;            };&lt;br /&gt;            addEvent(items, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;click&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (e) {&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;||&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; window.event;&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; src &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e.target &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;||&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e.srcElement;&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;try&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; {&lt;br /&gt;                    e.preventDefault();&lt;br /&gt;                }&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;catch&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (ex) {&lt;br /&gt;                    e.returnValue &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;                }&lt;br /&gt;                actionDispatcher(src.id);&lt;br /&gt;            });&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; adders &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;adders&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br /&gt;            addEvent(adders, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;click&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (e) {&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;||&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; window.event;&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; src &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e.target &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;||&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; e.srcElement;&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;try&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; {&lt;br /&gt;                    e.preventDefault();&lt;br /&gt;                }&lt;br /&gt;                &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;catch&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; (ex) {&lt;br /&gt;                    e.returnValue &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;br /&gt;                }&lt;br /&gt;                addRequest(src.id);&lt;br /&gt;            });&lt;br /&gt;        });&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;style &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/css"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; media&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="screen"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br /&gt;        body&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            font&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 100% georgia,times,serif&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br /&gt;        h1, h2&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            font-weight&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; normal&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br /&gt;        #queue-items&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            height&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 1.5em&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br /&gt;        #add-stuff&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            padding&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; .5em&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            background&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; #ddd&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            border&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 1px solid #bbb&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br /&gt;        #results-area&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            padding&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; .5em&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;            border&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt; 1px solid #bbb&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #ff0000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;style&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="example"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="doc"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            异步联接请求&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="queue-items"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="add-stuff"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;向队列里添加新请求&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ul &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="adders"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="#"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="action-01"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;添加 "01" 到队列&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="#"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="action-02"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;添加 "02" 到队列&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="#"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="action-03"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;添加 "03" 到队列&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ul&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;队列控制&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ul &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;='items'&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="#"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="flush"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Flush&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="#"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="dequeue"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;出列Dequeue&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="#"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="pause"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;暂停Pause&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;a &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="#"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="clear"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;清空Clear&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ul&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="results-area"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                结果:&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h2&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="results"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;在这个示例里，你可以做flush队列，暂停队列，删除队列里的请求，清空队列等各种动作，同时相信大家也体会到了桥接的威力了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;桥接模式的优点也很明显，我们只列举主要几个优点：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;分离接口和实现部分，一个实现未必不变地绑定在一个接口上，抽象类（函数）的实现可以在运行时刻进行配置，一个对象甚至可以在运行时刻改变它的实现，同将抽象和实现也进行了充分的解耦，也有利于分层，从而产生更好的结构化系统。&lt;/li&gt;&lt;li&gt;提高可扩充性&lt;/li&gt;&lt;li&gt;实现细节对客户透明，可以对客户隐藏实现细节。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;同时桥接模式也有自己的缺点：&lt;/p&gt;&lt;p&gt;大量的类将导致开发成本的增加，同时在性能方面可能也会有所减少。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2437321.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/19/2437321.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/18/2437099.html</id><title type="text">深入理解JavaScript系列（43）：设计模式之状态模式</title><summary type="text">介绍状态模式（State）允许一个对象在其内部状态改变的时候改变它的行为，对象看起来似乎修改了它的类。正文举个例子，就比如我们平时在下载东西，通常就会有好几个状态，比如准备状态（ReadyState）、下载状态（DownloadingState）、暂停状态（DownloadPausedState）、下载完毕状态（DownloadedState）、失败状态（DownloadFailedState），也就是说在每个状态都只可以做当前状态才可以做的事情，而不能做其它状态能做的事儿。由于State模式描述了下载（Download）如何在每一种状态下表现出不同的行为。这一模式的关键思想就是引入了一个叫做</summary><published>2012-04-17T22:56:00Z</published><updated>2012-04-17T22:56:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/18/2437099.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/18/2437099.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;状态模式（State）允许一个对象在其内部状态改变的时候改变它的行为，对象看起来似乎修改了它的类。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;正文&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;举个例子，就比如我们平时在下载东西，通常就会有好几个状态，比如准备状态（ReadyState）、下载状态（DownloadingState）、暂停状态（DownloadPausedState）、下载完毕状态（DownloadedState）、失败状态（DownloadFailedState），也就是说在每个状态都只可以做当前状态才可以做的事情，而不能做其它状态能做的事儿。&lt;/p&gt;&lt;p&gt;由于State模式描述了下载（Download）如何在每一种状态下表现出不同的行为。这一模式的关键思想就是引入了一个叫做State的抽象类（或JS里的函数）来表示下载状态，State函数（作为原型）为每个状态的子类（继承函数）声明了一些公共接口。其每个继承函数实现与特定状态相关的行为，比如DownloadingState和DownloadedState分别实现了正在下载和下载完毕的行为。这些行为可以通过Download来来维护。&lt;/p&gt;&lt;p&gt;让我们来实现一把，首先定义作为其他基础函数的原型的State函数：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; State = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;State.prototype.download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须被重载!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;State.prototype.pause = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须被重载!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;State.prototype.fail = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须被重载!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;State.prototype.finish = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须被重载!");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;我们为State的原型定义了4个方法接口，分别对应着下载（download）、暂停（pause）、失败（fail）、结束（finish）以便子函数可以重写。&lt;/p&gt;&lt;p&gt;在编写子函数之前，我们先来编写一个ReadyState函数，以便可以将状态传递给第一个download状态：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; ReadyState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oDownload) {&lt;br /&gt;    State.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload = oDownload;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;ReadyState.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; State();&lt;br /&gt;&lt;br /&gt;ReadyState.prototype.download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadingState());&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Ready以后，可以开始下载，所以设置了Download函数里的状态获取方法&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; console.log("Start Download!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;ReadyState.prototype.pause = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("还没开始下载，不能暂停!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;ReadyState.prototype.fail = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("文件还没开始下载，怎么能说失败呢!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;ReadyState.prototype.finish = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("文件还没开始下载，当然也不能结束了!");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;该函数接收了一个Download维护函数的实例作为参数，Download函数用于控制状态的改变和获取（类似于中央控制器，让外部调用），ReadyState重写了原型的download方法，以便开始进行下载。我们继续来看Download函数的主要功能：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oState = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ReadyState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.setState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oState) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oState = oState;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 对外暴露的四个公共方法，以便外部调用&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Download.prototype.download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oState.download();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.pause = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oState.pause();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.fail = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oState.fail();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.finish = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oState.finish();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;获取各种状态，传入当前this对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;Download.prototype.getReadyState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ReadyState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.getDownloadingState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DownloadingState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.getDownloadPausedState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DownloadPausedState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.getDownloadedState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DownloadedState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Download.prototype.getDownloadedFailedState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DownloadFailedState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;Download函数的原型提供了8个方法，4个是对用于下载状态的操作行为，另外4个是用于获取当前四个不同的状态，这4个方法都接收this作为参数，也就是将Download实例自身作为一个参数传递给处理该请求的状态对象（ReadyState 以及后面要实现的继承函数），这使得状态对象比必要的时候可以访问oDownlaod。&lt;/p&gt;&lt;p&gt;接下来，继续定义4个相关状态的函数：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; DownloadingState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oDownload) {&lt;br /&gt;    State.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload = oDownload;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadingState.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; State();&lt;br /&gt;&lt;br /&gt;DownloadingState.prototype.download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("文件已经正在下载中了!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadingState.prototype.pause = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () { &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadPausedState());&lt;br /&gt;    console.log("暂停下载!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadingState.prototype.fail = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () { &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadedFailedState());&lt;br /&gt;    console.log("下载失败!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadingState.prototype.finish = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadedState());&lt;br /&gt;    console.log("下载完毕!");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;DownloadingState的主要注意事项就是已经正在下载的文件，不能再次开始下载了，其它的状态都可以连续进行。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; DownloadPausedState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oDownload) {&lt;br /&gt;    State.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload = oDownload;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadPausedState.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; State();&lt;br /&gt;&lt;br /&gt;DownloadPausedState.prototype.download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadingState());&lt;br /&gt;    console.log("继续下载!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadPausedState.prototype.pause = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("已经暂停了，咋还要暂停呢!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadPausedState.prototype.fail = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () { &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadedFailedState());&lt;br /&gt;    console.log("下载失败!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadPausedState.prototype.finish = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadedState());&lt;br /&gt;    console.log("下载完毕!");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;DownloadPausedState函数里要注意的是，已经暂停的下载，不能再次暂停。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; DownloadedState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oDownload) {&lt;br /&gt;    State.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload = oDownload;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadedState.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; State();&lt;br /&gt;&lt;br /&gt;DownloadedState.prototype.download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadingState());&lt;br /&gt;    console.log("重新下载!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadedState.prototype.pause = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("对下载完了，还暂停啥？");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadedState.prototype.fail = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("都下载成功了，咋会失败呢？");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadedState.prototype.finish = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("下载成功了，不能再为成功了吧!");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;DownloadedState函数，同理成功下载以后，不能再设置finish了，只能设置重新下载状态。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; DownloadFailedState = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oDownload) {&lt;br /&gt;    State.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload = oDownload;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadFailedState.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; State();&lt;br /&gt;&lt;br /&gt;DownloadFailedState.prototype.download = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.setState(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oDownload.getDownloadingState());&lt;br /&gt;    console.log("尝试重新下载!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadFailedState.prototype.pause = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("失败的下载，也不能暂停!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadFailedState.prototype.fail = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("都失败了，咋还失败呢!");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DownloadFailedState.prototype.finish = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("失败的下载，肯定也不会成功!");&lt;br /&gt;};同理，DownloadFailedState函数的失败状态，也不能再次失败，但可以和finished以后再次尝试重新下载。&lt;/div&gt;&lt;p&gt;调用测试代码，就非常简单了，我们在HTML里演示吧，首先是要了jquery，然后有3个按钮分别代表：开始下载、暂停、重新下载。（注意在Firefox里用firebug查看结果，因为用了 console.log方法）。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;link &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/css"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; rel&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="stylesheet"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; href&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="http://www.cnblogs.com/css/style.css"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;State Pattern&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/jquery.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Download.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="states/State.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="states/DownloadFailedState.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="states/DownloadPausedState.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="states/DownloadedState.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="states/DownloadingState.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="states/ReadyState.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;input &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="button"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="开始下载"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="download_button"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;input &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="button"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="暂停"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="pause_button"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;input &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="button"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="重新下载"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="resume_button"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;var&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; oDownload &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt; &lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; Download();&lt;br /&gt;        $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;#download_button&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;).click(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () {&lt;br /&gt;            oDownload.download();&lt;br /&gt;        });&lt;br /&gt;&lt;br /&gt;        $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;#pause_button&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;).click(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () {&lt;br /&gt;            oDownload.pause();&lt;br /&gt;        });&lt;br /&gt;&lt;br /&gt;        $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;#resume_button&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;).click(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () {&lt;br /&gt;            oDownload.download();&lt;br /&gt;        });&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;状态模式的使用场景也特别明确，有如下两点：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;一个对象的行为取决于它的状态，并且它必须在运行时刻根据状态改变它的行为。&lt;/li&gt;&lt;li&gt;一个操作中含有大量的分支语句，而且这些分支语句依赖于该对象的状态。状态通常为一个或多个枚举常量的表示。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;参考：https://github.com/tcorral/Design-Patterns-in-Javascript/blob/master/State/1/index.html&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2437099.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/18/2437099.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/16/2436460.html</id><title type="text">深入理解JavaScript系列（42）：设计模式之原型模式</title><summary type="text">介绍原型模式（prototype）是指用原型实例指向创建对象的种类，并且通过拷贝这些原型创建新的对象。正文对于原型模式，我们可以利用JavaScript特有的原型继承特性去创建对象的方式，也就是创建的一个对象作为另外一个对象的prototype属性值。原型对象本身就是有效地利用了每个构造器创建的对象，例如，如果一个构造函数的原型包含了一个name属性（见后面的例子），那通过这个构造函数创建的对象都会有这个属性。在现有的文献里查看原型模式的定义，没有针对JavaScript的，你可能发现很多讲解的都是关于类的，但是现实情况是基于原型继承的JavaScript完全避免了类（class）的概念。我们</summary><published>2012-04-16T01:11:00Z</published><updated>2012-04-16T01:11:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/16/2436460.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/16/2436460.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;原型模式（prototype）是指用原型实例指向创建对象的种类，并且通过拷贝这些原型创建新的对象。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;正文&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于原型模式，我们可以利用JavaScript特有的原型继承特性去创建对象的方式，也就是创建的一个对象作为另外一个对象的prototype属性值。原型对象本身就是有效地利用了每个构造器创建的对象，例如，如果一个构造函数的原型包含了一个name属性（见后面的例子），那通过这个构造函数创建的对象都会有这个属性。&lt;/p&gt;&lt;p&gt;在现有的文献里查看原型模式的定义，没有针对JavaScript的，你可能发现很多讲解的都是关于类的，但是现实情况是基于原型继承的JavaScript完全避免了类（class）的概念。我们只是简单从现有的对象进行拷贝来创建对象。&lt;/p&gt;&lt;p&gt;真正的原型继承是作为最新版的ECMAScript5标准提出的，使用Object.create方法来创建这样的对象，该方法创建指定的对象，其对象的prototype有指定的对象（也就是该方法传进的第一个参数对象），也可以包含其他可选的指定属性。例如Object.create(prototype, optionalDescriptorObjects)，下面的例子里也可以看到这个用法：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 因为不是构造函数，所以不用大写&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; someCar = {&lt;br /&gt;    drive: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () { },&lt;br /&gt;    name: '马自达 3'&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 使用Object.create创建一个新车x&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; anotherCar = Object.create(someCar);&lt;br /&gt;anotherCar.name = '丰田佳美';&lt;/div&gt;&lt;p&gt;Object.create运行你直接从其它对象继承过来，使用该方法的第二个参数，你可以初始化额外的其它属性。例如：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; vehicle = {&lt;br /&gt;    getModel: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        console.log('车辆的模具是：' + &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.model);&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; car = Object.create(vehicle, {&lt;br /&gt;    'id': {&lt;br /&gt;        value: MY_GLOBAL.nextId(),&lt;br /&gt;        enumerable: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 默认writable:false, configurable:false&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; },&lt;br /&gt;    'model': {&lt;br /&gt;        value: '福特',&lt;br /&gt;        enumerable: &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;});&lt;/div&gt;&lt;p&gt;这里，可以在Object.create的第二个参数里使用对象字面量传入要初始化的额外属性，其语法与Object.defineProperties或Object.defineProperty方法类型。它允许您设定属性的特性，例如enumerable, writable 或 configurable。&lt;/p&gt;&lt;p&gt;如果你希望自己去实现原型模式，而不直接使用Object.create 。你可以使用像下面这样的代码为上面的例子来实现：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; vehiclePrototype = {&lt;br /&gt;    init: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (carModel) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.model = carModel;&lt;br /&gt;    },&lt;br /&gt;    getModel: &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        console.log('车辆模具是：' + &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.model);&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; vehicle(model) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; F() { };&lt;br /&gt;    F.prototype = vehiclePrototype;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; f = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; F();&lt;br /&gt;&lt;br /&gt;    f.init(model);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; f;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; car = vehicle('福特Escort');&lt;br /&gt;car.getModel();&lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;原型模式在JavaScript里的使用简直是无处不在，其它很多模式有很多也是基于prototype的，就不多说了，这里大家要注意的依然是浅拷贝和深拷贝的问题，免得出现引用问题。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2436460.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/16/2436460.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/13/2436371.html</id><title type="text">深入理解JavaScript系列（41）：设计模式之模板方法</title><summary type="text">介绍模板方法（TemplateMethod）定义了一个操作中的算法的骨架，而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法是一种代码复用的基本技术，在类库中尤为重要，因为他们提取了类库中的公共行为。模板方法导致一种反向的控制结构，这种结构就是传说中的“好莱坞法则”，即“别找找我们，我们找你”，这指的是父类调用一个类的操作，而不是相反。具体体现是面向对象编程编程语言里的抽象类（以及其中的抽象方法），以及继承该抽象类（和抽象方法）的子类。正文举个例子，泡茶和泡咖啡有同样的步骤，比如烧开水（boilWater）、冲泡（brew）、倒在杯子里（</summary><published>2012-04-13T01:04:00Z</published><updated>2012-04-13T01:04:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/13/2436371.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/13/2436371.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;模板方法（TemplateMethod）定义了一个操作中的算法的骨架，而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。&lt;/p&gt;&lt;p&gt;模板方法是一种代码复用的基本技术，在类库中尤为重要，因为他们提取了类库中的公共行为。模板方法导致一种反向的控制结构，这种结构就是传说中的&amp;ldquo;好莱坞法则&amp;rdquo;，即&amp;ldquo;别找找我们，我们找你&amp;rdquo;，这指的是父类调用一个类的操作，而不是相反。具体体现是面向对象编程编程语言里的抽象类（以及其中的抽象方法），以及继承该抽象类（和抽象方法）的子类。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;正文&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;举个例子，泡茶和泡咖啡有同样的步骤，比如烧开水（boilWater）、冲泡（brew）、倒在杯子里（pourOnCup），加小料（addCondiments）等等。但每种饮料冲泡的方法以及所加的小料不一样，所以我们可以利用模板方法实现这个主要步骤。&lt;/p&gt;&lt;p&gt;首先先来定义抽象步骤：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; CaffeineBeverage = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;CaffeineBeverage.prototype.prepareRecipe = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.boilWater();&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.brew();&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.pourOnCup();&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.customerWantsCondiments()) {&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 如果可以想加小料，就加上&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.addCondiments();&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;CaffeineBeverage.prototype.boilWater = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("将水烧开!");&lt;br /&gt;};&lt;br /&gt;CaffeineBeverage.prototype.pourOnCup = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("将饮料到再杯子里!");&lt;br /&gt;};&lt;br /&gt;CaffeineBeverage.prototype.brew = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;CaffeineBeverage.prototype.addCondiments = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 默认加上小料&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;CaffeineBeverage.prototype.customerWantsCondiments = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;;&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;该函数在原型上扩展了所有的基础步骤，以及主要步骤，冲泡和加小料步骤没有实现，供具体饮料所对应的函数来实现，另外是否加小料（customerWantsCondiments ）默认返回true，子函数重写的时候可以重写该值。&lt;/p&gt;&lt;p&gt;下面两个函数分别是冲咖啡和冲茶所对应的函数：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 冲咖啡&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Coffee = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    CaffeineBeverage.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;Coffee.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; CaffeineBeverage();&lt;br /&gt;Coffee.prototype.brew = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("从咖啡机想咖啡倒进去!");&lt;br /&gt;};&lt;br /&gt;Coffee.prototype.addCondiments = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("添加糖和牛奶");&lt;br /&gt;};&lt;br /&gt;Coffee.prototype.customerWantsCondiments = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; confirm("你想添加糖和牛奶吗？");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;冲茶叶&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Tea = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    CaffeineBeverage.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;Tea.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; CaffeineBeverage();&lt;br /&gt;Tea.prototype.brew = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("泡茶叶!");&lt;br /&gt;};&lt;br /&gt;Tea.prototype.addCondiments = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("添加柠檬!");&lt;br /&gt;};&lt;br /&gt;Tea.prototype.customerWantsCondiments = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; confirm("你想添加柠檬嘛？");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;另外使用confirm，可以让用户自己选择加不加小料，很不错，不是嘛？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;模板方法应用于下列情况：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;一次性实现一个算法的不变的部分，并将可变的行为留给子类来实现&lt;/li&gt;&lt;li&gt;各子类中公共的行为应被提取出来并集中到一个公共父类中的避免代码重复，不同之处分离为新的操作，最后，用一个钓鱼这些新操作的模板方法来替换这些不同的代码&lt;/li&gt;&lt;li&gt;控制子类扩展，模板方法只在特定点调用&amp;ldquo;hook&amp;rdquo;操作，这样就允许在这些点进行扩展&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;和策略模式不同，模板方法使用继承来改变算法的一部分，而策略模式使用委托来改变整个算法。&lt;/p&gt;&lt;p&gt;参考：https://github.com/tcorral/Design-Patterns-in-Javascript/blob/master/Template/withHook/index.html&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2436371.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/13/2436371.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/12/2435530.html</id><title type="text">深入理解JavaScript系列（40）：设计模式之组合模式</title><summary type="text">介绍组合模式（Composite）将对象组合成树形结构以表示“部分-整体”的层次结构，组合模式使得用户对单个对象和组合对象的使用具有一致性。常见的场景有asp.net里的控件机制（即control里可以包含子control，可以递归操作、添加、删除子control），类似的还有DOM的机制，一个DOM节点可以包含子节点，不管是父节点还是子节点都有添加、删除、遍历子节点的通用功能。所以说组合模式的关键是要有一个抽象类，它既可以表示子元素，又可以表示父元素。正文举个例子，有家餐厅提供了各种各样的菜品，每个餐桌都有一本菜单，菜单上列出了该餐厅所偶的菜品，有早餐糕点、午餐、晚餐等等，每个餐都有各种各样</summary><published>2012-04-12T00:35:00Z</published><updated>2012-04-12T00:35:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/12/2435530.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/12/2435530.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;组合模式（Composite）将对象组合成树形结构以表示&amp;ldquo;部分-整体&amp;rdquo;的层次结构，组合模式使得用户对单个对象和组合对象的使用具有一致性。&lt;/p&gt;&lt;p&gt;常见的场景有asp.net里的控件机制（即control里可以包含子control，可以递归操作、添加、删除子control），类似的还有DOM的机制，一个DOM节点可以包含子节点，不管是父节点还是子节点都有添加、删除、遍历子节点的通用功能。所以说组合模式的关键是要有一个抽象类，它既可以表示子元素，又可以表示父元素。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;正文&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;举个例子，有家餐厅提供了各种各样的菜品，每个餐桌都有一本菜单，菜单上列出了该餐厅所偶的菜品，有早餐糕点、午餐、晚餐等等，每个餐都有各种各样的菜单项，假设不管是菜单项还是整个菜单都应该是可以打印的，而且可以添加子项，比如午餐可以添加新菜品，而菜单项咖啡也可以添加糖啊什么的。&lt;/p&gt;&lt;p&gt;这种情况，我们就可以利用组合的方式将这些内容表示为层次结构了。我们来逐一分解一下我们的实现步骤。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第一步，先实现我们的&amp;ldquo;抽象类&amp;rdquo;函数MenuComponent：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; MenuComponent = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.getName = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.getDescription = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.getPrice = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.isVegetarian = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.print = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.add = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.remove = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;br /&gt;MenuComponent.prototype.getChild = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须重写!");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;该函数提供了2种类型的方法，一种是获取信息的，比如价格，名称等，另外一种是通用操作方法，比如打印、添加、删除、获取子菜单。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第二步，创建基本的菜品项：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; MenuItem = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (sName, sDescription, bVegetarian, nPrice) {&lt;br /&gt;    MenuComponent.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sName = sName;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sDescription = sDescription;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.bVegetarian = bVegetarian;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.nPrice = nPrice;&lt;br /&gt;};&lt;br /&gt;MenuItem.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MenuComponent();&lt;br /&gt;MenuItem.prototype.getName = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sName;&lt;br /&gt;};&lt;br /&gt;MenuItem.prototype.getDescription = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sDescription;&lt;br /&gt;};&lt;br /&gt;MenuItem.prototype.getPrice = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.nPrice;&lt;br /&gt;};&lt;br /&gt;MenuItem.prototype.isVegetarian = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.bVegetarian;&lt;br /&gt;};&lt;br /&gt;MenuItem.prototype.print = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.getName() + ": " + &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.getDescription() + ", " + &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.getPrice() + "euros");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;由代码可以看出，我们只重新了原型的4个获取信息的方法和print方法，没有重载其它3个操作方法，因为基本菜品不包含添加、删除、获取子菜品的方式。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第三步，创建菜品：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Menu = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (sName, sDescription) {&lt;br /&gt;    MenuComponent.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents = [];&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sName = sName;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sDescription = sDescription;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.createIterator = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("This method must be overwritten!");&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;Menu.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MenuComponent();&lt;br /&gt;Menu.prototype.add = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oMenuComponent) {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 添加子菜品&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents.push(oMenuComponent);&lt;br /&gt;};&lt;br /&gt;Menu.prototype.remove = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (oMenuComponent) {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 删除子菜品&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; aMenuItems = [];&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; nMenuItem = 0;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; nLenMenuItems = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents.length;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oItem = &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (; nMenuItem &amp;lt; nLenMenuItems; ) {&lt;br /&gt;        oItem = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents[nMenuItem];&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (oItem !== oMenuComponent) {&lt;br /&gt;            aMenuItems.push(oItem);&lt;br /&gt;        }&lt;br /&gt;        nMenuItem = nMenuItem + 1;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents = aMenuItems;&lt;br /&gt;};&lt;br /&gt;Menu.prototype.getChild = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (nIndex) {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;获取指定的子菜品&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents[nIndex];&lt;br /&gt;};&lt;br /&gt;Menu.prototype.getName = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sName;&lt;br /&gt;};&lt;br /&gt;Menu.prototype.getDescription = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.sDescription;&lt;br /&gt;};&lt;br /&gt;Menu.prototype.print = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 打印当前菜品以及所有的子菜品&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    console.log(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.getName() + ": " + &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.getDescription());&lt;br /&gt;    console.log("--------------------------------------------");&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; nMenuComponent = 0;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; nLenMenuComponents = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents.length;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oMenuComponent = &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (; nMenuComponent &amp;lt; nLenMenuComponents; ) {&lt;br /&gt;        oMenuComponent = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenuComponents[nMenuComponent];&lt;br /&gt;        oMenuComponent.print();&lt;br /&gt;        nMenuComponent = nMenuComponent + 1;&lt;br /&gt;    }&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;注意上述代码，除了实现了添加、删除、获取方法外，打印print方法是首先打印当前菜品信息，然后循环遍历打印所有子菜品信息。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第四步，创建指定的菜品：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们可以创建几个真实的菜品，比如晚餐、咖啡、糕点等等，其都是用Menu作为其原型，代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; DinnerMenu = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    Menu.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;DinnerMenu.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Menu();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; CafeMenu = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    Menu.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;CafeMenu.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Menu();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; PancakeHouseMenu = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    Menu.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;PancakeHouseMenu.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Menu();&lt;/div&gt;&lt;p&gt;&lt;strong&gt;第五步，创建最顶级的菜单容器&amp;mdash;&amp;mdash;菜单本：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Mattress = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; (aMenus) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenus = aMenus;&lt;br /&gt;};&lt;br /&gt;Mattress.prototype.printMenu = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.aMenus.print();&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;该函数接收一个菜单数组作为参数，并且值提供了printMenu方法用于打印所有的菜单内容。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第六步，调用方式：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oPanCakeHouseMenu = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Menu("Pancake House Menu", "Breakfast");&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oDinnerMenu = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Menu("Dinner Menu", "Lunch");&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oCoffeeMenu = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Menu("Cafe Menu", "Dinner");&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oAllMenus = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Menu("ALL MENUS", "All menus combined");&lt;br /&gt;&lt;br /&gt;oAllMenus.add(oPanCakeHouseMenu);&lt;br /&gt;oAllMenus.add(oDinnerMenu);&lt;br /&gt;&lt;br /&gt;oDinnerMenu.add(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MenuItem("Pasta", "Spaghetti with Marinara Sauce, and a slice of sourdough bread", &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;, 3.89));&lt;br /&gt;oDinnerMenu.add(oCoffeeMenu);&lt;br /&gt;&lt;br /&gt;oCoffeeMenu.add(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MenuItem("Express", "Coffee from machine", &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;, 0.99));&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oMattress = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Mattress(oAllMenus);&lt;br /&gt;console.log("---------------------------------------------");&lt;br /&gt;oMattress.printMenu();&lt;br /&gt;console.log("---------------------------------------------");&lt;/div&gt;&lt;p&gt;熟悉asp.net控件开发的同学，是不是看起来很熟悉？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;组合模式的使用场景非常明确：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;你想表示对象的部分-整体层次结构时；&lt;/li&gt;&lt;li&gt;你希望用户忽略组合对象和单个对象的不同，用户将统一地使用组合结构中的所有对象（方法）&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;另外该模式经常和装饰者一起使用，它们通常有一个公共的父类（也就是原型），因此装饰必须支持具有add、remove、getChild操作的 component接口。&lt;/p&gt;&lt;p&gt;参考：https://github.com/tcorral/Design-Patterns-in-Javascript/blob/master/Composite/index.html&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2435530.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/12/2435530.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/TomXu/archive/2012/04/11/2435452.html</id><title type="text">深入理解JavaScript系列（39）：设计模式之适配器模式</title><summary type="text">介绍适配器模式（Adapter）是将一个类（对象）的接口（方法或属性）转化成客户希望的另外一个接口（方法或属性），适配器模式使得原本由于接口不兼容而不能一起工作的那些类（对象）可以一些工作。速成包装器（wrapper）。正文我们来举一个例子，鸭子（Dock）有飞（fly）和嘎嘎叫（quack）的行为，而火鸡虽然也有飞（fly）的行为，但是其叫声是咯咯的（gobble）。如果你非要火鸡也要实现嘎嘎叫（quack）这个动作，那我们可以复用鸭子的quack方法，但是具体的叫还应该是咯咯的，此时，我们就可以创建一个火鸡的适配器，以便让火鸡也支持quack方法，其内部还是要调用gobble。OK，我们开</summary><published>2012-04-11T01:16:00Z</published><updated>2012-04-11T01:16:00Z</updated><author><name>汤姆大叔</name><uri>http://www.cnblogs.com/TomXu/</uri></author><link rel="alternate" href="http://www.cnblogs.com/TomXu/archive/2012/04/11/2435452.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/TomXu/archive/2012/04/11/2435452.html"/><content type="html">&lt;p&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;适配器模式（Adapter）是将一个类（对象）的接口（方法或属性）转化成客户希望的另外一个接口（方法或属性），适配器模式使得原本由于接口不兼容而不能一起工作的那些类（对象）可以一些工作。速成包装器（wrapper）。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;正文&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们来举一个例子，鸭子（Dock）有飞（fly）和嘎嘎叫（quack）的行为，而火鸡虽然也有飞（fly）的行为，但是其叫声是咯咯的（gobble）。如果你非要火鸡也要实现嘎嘎叫（quack）这个动作，那我们可以复用鸭子的quack方法，但是具体的叫还应该是咯咯的，此时，我们就可以创建一个火鸡的适配器，以便让火鸡也支持quack方法，其内部还是要调用gobble。&lt;/p&gt;&lt;p&gt;OK，我们开始一步一步实现，首先要先定义鸭子和火鸡的抽象行为，也就是各自的方法函数：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;鸭子&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Duck = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;Duck.prototype.fly = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须被重写!");&lt;br /&gt;};&lt;br /&gt;Duck.prototype.quack = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error("该方法必须被重写!");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;火鸡&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; Turkey = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;Turkey.prototype.fly = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error(" 该方法必须被重写 !");&lt;br /&gt;};&lt;br /&gt;Turkey.prototype.gobble = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Error(" 该方法必须被重写 !");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;然后再定义具体的鸭子和火鸡的构造函数，分别为：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;鸭子&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; MallardDuck = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    Duck.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;MallardDuck.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Duck(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;原型是Duck&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;MallardDuck.prototype.fly = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("可以飞翔很长的距离!");&lt;br /&gt;};&lt;br /&gt;MallardDuck.prototype.quack = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("嘎嘎！嘎嘎！");&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;火鸡&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; WildTurkey = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    Turkey.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;};&lt;br /&gt;WildTurkey.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Turkey(); &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;原型是Turkey&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;WildTurkey.prototype.fly = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("飞翔的距离貌似有点短!");&lt;br /&gt;};&lt;br /&gt;WildTurkey.prototype.gobble = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt; () {&lt;br /&gt;    console.log("咯咯！咯咯！");&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;为了让火鸡也支持quack方法，我们创建了一个新的火鸡适配器TurkeyAdapter：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; TurkeyAdapter = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(oTurkey){&lt;br /&gt;    Duck.apply(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oTurkey = oTurkey;&lt;br /&gt;};&lt;br /&gt;TurkeyAdapter.prototype = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Duck();&lt;br /&gt;TurkeyAdapter.prototype.quack = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oTurkey.gobble();&lt;br /&gt;};&lt;br /&gt;TurkeyAdapter.prototype.fly = &lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;(){&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; nFly = 0;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; nLenFly = 5;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt;(; nFly &amp;lt; nLenFly;){&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.oTurkey.fly();&lt;br /&gt;        nFly = nFly + 1;&lt;br /&gt;    }&lt;br /&gt;};&lt;/div&gt;&lt;p&gt;该构造函数接受一个火鸡的实例对象，然后使用Duck进行apply，其适配器原型是Duck，然后要重新修改其原型的quack方法，以便内部调用oTurkey.gobble()方法。其fly方法也做了一些改变，让火鸡连续飞5次（内部也是调用自身的oTurkey.fly()方法）。&lt;/p&gt;&lt;p&gt;调用方法，就很明了了，测试一下便可以知道结果了：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oMallardDuck = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MallardDuck();&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oWildTurkey = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; WildTurkey();&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; oTurkeyAdapter = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; TurkeyAdapter(oWildTurkey);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;原有的鸭子行为&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;oMallardDuck.fly();&lt;br /&gt;oMallardDuck.quack();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;原有的火鸡行为&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;oWildTurkey.fly();&lt;br /&gt;oWildTurkey.gobble();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;适配器火鸡的行为（火鸡调用鸭子的方法名称）&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;oTurkeyAdapter.fly();&lt;br /&gt;oTurkeyAdapter.quack();&lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;那合适使用适配器模式好呢？如果有以下情况出现时，建议使用：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;使用一个已经存在的对象，但其方法或属性接口不符合你的要求；&lt;/li&gt;&lt;li&gt;你想创建一个可复用的对象，该对象可以与其它不相关的对象或不可见对象（即接口方法或属性不兼容的对象）协同工作；&lt;/li&gt;&lt;li&gt;想使用已经存在的对象，但是不能对每一个都进行原型继承以匹配它的接口。对象适配器可以适配它的父对象接口方法或属性。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;另外，适配器模式和其它几个模式可能容易让人迷惑，这里说一下大概的区别：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;适配器和桥接模式虽然类似，但桥接的出发点不同，桥接的目的是将接口部分和实现部分分离，从而对他们可以更为容易也相对独立的加以改变。而适配器则意味着改变一个已有对象的接口。&lt;/li&gt;&lt;li&gt;装饰者模式增强了其它对象的功能而同时又不改变它的接口，因此它对应程序的透明性比适配器要好，其结果是装饰者支持递归组合，而纯粹使用适配器则是不可能的。&lt;/li&gt;&lt;li&gt;代理模式在不改变它的接口的条件下，为另外一个对象定义了一个代理。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;参考：https://github.com/tcorral/Design-Patterns-in-Javascript/blob/master/Adapter/index.html&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步与推荐&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本文已同步至目录索引：&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html" target="_blank"&gt;深入理解JavaScript系列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;深入理解JavaScript系列文章，包括了原创，翻译，转载等各类型的文章，如果对你有用，请推荐支持一把，给大叔写作的动力。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/TomXu/aggbug/2435452.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/TomXu/archive/2012/04/11/2435452.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
