在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 對象創(chuàng)建模式(下篇)
代碼復(fù)用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設(shè)計模式之狀態(tài)模式
JavaScript 核心(晉級高手必讀篇)
設(shè)計模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設(shè)計模式之中介者模式
設(shè)計模式之裝飾者模式
設(shè)計模式之模板方法
設(shè)計模式之外觀模式
強大的原型和原型鏈
設(shè)計模式之構(gòu)造函數(shù)模式
揭秘命名函數(shù)表達式
深入理解J avaScript 系列(結(jié)局篇)
執(zhí)行上下文(Execution Contexts)
函數(shù)(Functions)
《你真懂 JavaScript 嗎?》答案詳解
設(shè)計模式之適配器模式
設(shè)計模式之組合模式
設(shè)計模式之命令模式
S.O.L.I.D 五大原則之單一職責 SRP
編寫高質(zhì)量 JavaScript 代碼的基本要點
求值策略
閉包(Closures)
對象創(chuàng)建模式(上篇)
This? Yes,this!
設(shè)計模式之代理模式
變量對象(Variable Object)
S.O.L.I.D 五大原則之里氏替換原則 LSP
面向?qū)ο缶幊讨话憷碚?/span>
設(shè)計模式之單例模式
Function 模式(上篇)
S.O.L.I.D 五大原則之依賴倒置原則 DIP
設(shè)計模式之迭代器模式
立即調(diào)用的函數(shù)表達式
設(shè)計模式之享元模式
設(shè)計模式之原型模式
根本沒有“JSON 對象”這回事!
JavaScript 與 DOM(下)
面向?qū)ο缶幊讨?ECMAScript 實現(xiàn)
全面解析 Module 模式
對象創(chuàng)建模式(下篇)
設(shè)計模式之職責鏈模式
S.O.L.I.D 五大原則之開閉原則 OCP
設(shè)計模式之橋接模式
設(shè)計模式之策略模式
設(shè)計模式之觀察者模式
代碼復(fù)用模式(推薦篇)
作用域鏈(Scope Chain)
Function 模式(下篇)
設(shè)計模式之工廠模式

對象創(chuàng)建模式(下篇)

介紹

本篇主要是介紹創(chuàng)建對象方面的模式的下篇,利用各種技巧可以極大地避免了錯誤或者可以編寫出非常精簡的代碼。

模式 6:函數(shù)語法糖

函數(shù)語法糖是為一個對象快速添加方法(函數(shù))的擴展,這個主要是利用 prototype 的特性,代碼比較簡單,我們先來看一下實現(xiàn)代碼:

if (typeof Function.prototype.method !== "function") {
    Function.prototype.method = function (name, implementation) {
        this.prototype[name] = implementation;
        return this;
    };
}

擴展對象的時候,可以這么用:

var Person = function (name) {
    this.name = name;
}
.method('getName',
            function () {
                return this.name;
            })
.method('setName', function (name) {
    this.name = name;
    return this;
});

這樣就給 Person 函數(shù)添加了 getName 和 setName 這 2 個方法,接下來我們來驗證一下結(jié)果:

var a = new Person('Adam');
console.log(a.getName()); // 'Adam'
console.log(a.setName('Eve').getName()); // 'Eve'

模式 7:對象常量

對象常量是在一個對象提供 set,get,ifDefined 各種方法的體現(xiàn),而且對于 set 的方法只會保留最先設(shè)置的對象,后期再設(shè)置都是無效的,已達到別人無法重載的目的。實現(xiàn)代碼如下:

var constant = (function () {
    var constants = {},
        ownProp = Object.prototype.hasOwnProperty,
    // 只允許設(shè)置這三種類型的值
        allowed = {
            string: 1,
            number: 1,
            boolean: 1
        },
        prefix = (Math.random() + "_").slice(2);  
    return {
        // 設(shè)置名稱為name的屬性
        set: function (name, value) {
            if (this.isDefined(name)) {
                return false;
            }
            if (!ownProp.call(allowed, typeof value)) {
                return false;
            }
            constants[prefix + name] = value;
            return true;
        },
        // 判斷是否存在名稱為name的屬性
        isDefined: function (name) {
            return ownProp.call(constants, prefix + name);
        },
        // 獲取名稱為name的屬性
        get: function (name) {
            if (this.isDefined(name)) {
                return constants[prefix + name];
            }
            return null;
        }
    };
} ());

驗證代碼如下:

// 檢查是否存在
console.log(constant.isDefined("maxwidth")); // false  
// 定義
console.log(constant.set("maxwidth", 480)); // true  
// 重新檢測
console.log(constant.isDefined("maxwidth")); // true  
// 嘗試重新定義
console.log(constant.set("maxwidth", 320)); // false  
// 判斷原先的定義是否還存在
console.log(constant.get("maxwidth")); // 480

模式 8:沙盒模式

沙盒(Sandbox)模式即時為一個或多個模塊提供單獨的上下文環(huán)境,而不會影響其他模塊的上下文環(huán)境,比如有個 Sandbox 里有 3 個方法event,dom,ajax,在調(diào)用其中 2 個組成一個環(huán)境的話,和調(diào)用三個組成的環(huán)境完全沒有干擾。Sandbox 實現(xiàn)代碼如下:

function Sandbox() {
    // 將參數(shù)轉(zhuǎn)為數(shù)組
    var args = Array.prototype.slice.call(arguments),
    // 最后一個參數(shù)為callback
        callback = args.pop(),
        // 除最后一個參數(shù)外,其它均為要選擇的模塊
        modules = (args[0] && typeof args[0] === "string") ? args : args[0],
        i;  
    // 強制使用new操作符
    if (!(this instanceof Sandbox)) {
        return new Sandbox(modules, callback);
    }  
    // 添加屬性
    this.a = 1;
    this.b = 2;  
    // 向this對象上需想添加模塊
    // 如果沒有模塊或傳入的參數(shù)為 "*" ,則以為著傳入所有模塊
    if (!modules || modules == '*') {
        modules = [];
        for (i in Sandbox.modules) {
            if (Sandbox.modules.hasOwnProperty(i)) {
                modules.push(i);
            }
        }
    }  
    // 初始化需要的模塊
    for (i = 0; i < modules.length; i += 1) {
        Sandbox.modules[modules[i]](this);
    }
    // 調(diào)用 callback
    callback(this);
}  
// 默認添加原型對象
Sandbox.prototype = {
    name: "My Application",
    version: "1.0",
    getName: function () {
        return this.name;
    }
};

然后我們再定義默認的初始模塊:

Sandbox.modules = {};  
Sandbox.modules.dom = function (box) {
    box.getElement = function () {
    };
    box.getStyle = function () {
    };
    box.foo = "bar";
};  
Sandbox.modules.event = function (box) {
    // access to the Sandbox prototype if needed:
    // box.constructor.prototype.m = "mmm";
    box.attachEvent = function () {
    };
    box.detachEvent = function () {
    };
};  
Sandbox.modules.ajax = function (box) {
    box.makeRequest = function () {
    };
    box.getResponse = function () {
    };
};

調(diào)用方式如下:

// 調(diào)用方式
Sandbox(['ajax', 'event'], function (box) {
    console.log(typeof (box.foo));
    // 沒有選擇dom,所以box.foo不存在
});  
Sandbox('ajax', 'dom', function (box) {
    console.log(typeof (box.attachEvent));
    // 沒有選擇event,所以event里定義的attachEvent也不存在
});  
Sandbox('*', function (box) {
    console.log(box); // 上面定義的所有方法都可訪問
});

通過三個不同的調(diào)用方式,我們可以看到,三種方式的上下文環(huán)境都是不同的,第一種里沒有 foo;而第二種則沒有 attachEvent,因為只加載了 ajax 和 dom,而沒有加載 event;第三種則加載了全部。

模式 9:靜態(tài)成員

靜態(tài)成員(Static Members)只是一個函數(shù)或?qū)ο筇峁┑撵o態(tài)屬性,可分為私有的和公有的,就像 C#或 Java 里的 public static 和 private static 一樣。

我們先來看一下公有成員,公有成員非常簡單,我們平時聲明的方法,函數(shù)都是公有的,比如:

// 構(gòu)造函數(shù)
var Gadget = function () {
};  
// 公有靜態(tài)方法
Gadget.isShiny = function () {
    return "you bet";
};  
// 原型上添加的正常方法
Gadget.prototype.setPrice = function (price) {
    this.price = price;
};  
// 調(diào)用靜態(tài)方法
console.log(Gadget.isShiny()); // "you bet"  
// 創(chuàng)建實例,然后調(diào)用方法
var iphone = new Gadget();
iphone.setPrice(500);  
console.log(typeof Gadget.setPrice); // "undefined"
console.log(typeof iphone.isShiny); // "undefined"
Gadget.prototype.isShiny = Gadget.isShiny;
console.log(iphone.isShiny()); // "you bet"

而私有靜態(tài)成員,我們可以利用其閉包特性去實現(xiàn),以下是兩種實現(xiàn)方式。

第一種實現(xiàn)方式:

var Gadget = (function () {
    // 靜態(tài)變量/屬性
    var counter = 0;  
    // 閉包返回構(gòu)造函數(shù)的新實現(xiàn)
    return function () {
        console.log(counter += 1);
    };
} ()); // 立即執(zhí)行  
var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
var g3 = new Gadget(); // logs 3

可以看出,雖然每次都是 new 的對象,但數(shù)字依然是遞增的,達到了靜態(tài)成員的目的。

第二種方式:

var Gadget = (function () {
    // 靜態(tài)變量/屬性
    var counter = 0,
        NewGadget;  
    //新構(gòu)造函數(shù)實現(xiàn)
    NewGadget = function () {
        counter += 1;
   };  
    // 授權(quán)可以訪問的方法
    NewGadget.prototype.getLastId = function () {
        return counter;
    };  
    // 覆蓋構(gòu)造函數(shù)
    return NewGadget;
} ()); // 立即執(zhí)行  
var iphone = new Gadget();
iphone.getLastId(); // 1
var ipod = new Gadget();
ipod.getLastId(); // 2
var ipad = new Gadget();
ipad.getLastId(); // 3

數(shù)字也是遞增了,這是利用其內(nèi)部授權(quán)方法的閉包特性實現(xiàn)的。

總結(jié)

這是對象創(chuàng)建模式的下篇,兩篇一起總共9種模式,是我們在日常 JavaScript 編程中經(jīng)常使用的對象創(chuàng)建模式,不同的場景起到了不同的作用,希望大家根據(jù)各自的需求選擇適用的模式。

同步與推薦

深入理解 JavaScript 系列文章,包括了原創(chuàng),翻譯,轉(zhuǎn)載等各類型的文章,如果對你有用,請推薦支持一把,給大叔寫作的動力。