1. 程式人生 > >《JavaScript 模式》讀書筆記(5)— 物件建立模式4

《JavaScript 模式》讀書筆記(5)— 物件建立模式4

  我們學完了大部分物件建立模式相關的內容,下面還有一些小而精的部分。

 

七、物件常量

  JavaScript中沒有常量的概念,雖然許多現代的程式設計環境可能為您提供了用以建立常量的const語句。作為一種變通方案,JavaScript中常見的一種方法是使用命名約定,使那些不應該被修改的變數全部用大寫字母以突出顯示。實際上這個命名約定已經用於內建JavaScript物件中了。

console.log(Math.PI);
console.log(Math.SQRT2);

  對於您自己的常量,也可以採用相同的命名約定,並且將它們以靜態屬性的方式新增到建構函式中。

// 建構函式
var Widget = function () {
    // 實現...
};

// 常數
Widget.MAX_HEIGHT = 320;
Widget.MAX_WIDTH = 480;

  同樣的命名約定還可應用於以字面量建立的物件中,這些常量可以是以大寫字母命名的正常屬性。

  如果你真的想擁有一個不可變的值,可以建立一個私有屬性並提供一個取值(getter)方法,但並不提供設值函式(setter)。不過在許多情況下,當可以採用簡單的命名公約取值時,這種不提供設定函式的方法可能顯得矯枉過正。

  下面是一個通用的constant(常量)物件實現方法示例,它提供了下列方法:

  set(name, value)

    定義一個新的常量。

  isDefined(name)

    檢測是定常量是否存在。

  get(name)

    讀取指定常量的值。

  在這個實現中,只有原始值(primitive value)允許設為常量。此外,一些額外的注意事項是要確保宣告的常量與內建屬性名不會衝突,比如toString或hasOwnProperty等,可以通過使用hasOwnProperty()檢測名稱,並且在所有的常量名前面新增隨機生成的字首,從而確保名稱之間相互適應。

var constant = (function () {
    var constants = {},
        ownProp = Object.prototype.hasOwnProperty,
        allowed = {
            string:1,
            number:1,
            boolean:1
        },
        prefix = (Math.random() + "_").slice(2);
    
    return {
        set:function(name,value) {
            if(this.isDefined(name)) {
                return false;
            }
            if(!ownProp.call(allowed,typeof value)){
                return false;
            }
            constants[prefix + name] = value;
            return true;
        },
        isDefined:function(name) {
            return ownProp.call(constants,prefix + name);
        },
        get:function(name) {
            if(this.isDefined(name)){
                return constants[prefix + name];
            }
            return null;
        }
    }
}());

// 測試以上實現程式碼
// 檢查是否已經定義
constant.isDefined("maxwidth");

// 定義
constant.set('maxwidth',480);

// 再次檢查
constant.isDefined('maxwidth');

// 試圖重新定義
constant.set("maxwidth",320);

// 該值是否扔保持不變
constant.get("maxwidth");

  

八、鏈模式

  鏈模式(Chaining Pattern)可以使您能夠一個接一個的呼叫物件的方法,而無需將前一個操作返回的值賦給變數,並且無需將您的呼叫分割成多行:

myobj.method1("hello").method2().method3("world").method4();

  當建立的方法返回的是無任何意義的值時,可以使它們返回this,即正在使用的物件的示例。這將使物件的使用者呼叫前面連線的下一個方法:

var obj = {
    value:1,
    increment: function () {
        this.value += 1;
        return this;
    },
    add: function(v) {
        this.value += v;
        return this;
    },
    shout:function () {
        alert(this.value);
    }
};

// 鏈方法呼叫
obj.increment().add(3).shout();

  

鏈模式的優點和缺點

  使用鏈模式的一個優點在於可以節省一些輸入的字元,並且還可以建立更簡潔的程式碼,使其讀起來就像一個句子。

  另一個優點在於它可以幫助您考慮分割函式,以建立更加簡短、具有特定功能的函式,而不是建立嘗試實現太多功能的函式。從長遠來看,這提高了程式碼的可維護性。

  鏈模式的一個缺點在於以這種方式編寫的程式碼更加難以除錯。或許直到在某個特定的程式碼行中發生錯誤,但是在此行中實際執行了太多步驟。當鏈中多個方法其中一個靜默失效時,無法直到是哪一個方法失效了。

  在任何情況下,識別出這種模式都很有好處。當編寫的方法並沒有明顯和有意義的返回值時,可以總是返回this。該模式得到了廣泛的應用,比如在jQuery庫中就使用了該模式。此外,如果檢視DOM的API,那麼還可以注意到它的結構也傾向於鏈模式。

 

九、method()方法

  JavaScript可能會使用那些以類的方式思考的程式設計師感到困惑。這就是為什麼一些開發人員傾向於選擇使JavaScript更加類似類。其中一個這樣的嘗試是Douglas Crockford引入method()方法的思想。現在回想起來,他承認使JavaScript類似類的思想並不是值得推薦的方案,但是它仍然是一種令人關注的模式,有可能在一些應用程式中遇到這種模式。

  使用建構函式看起來就像是在使用Java中的類。它們還能夠支援您向建構函式主體中的this 新增例項屬性。然後這種向this新增方法的機制其實效率十分低下,原因在於它們最終都會與每個例項一起被重新建立,並且消耗更多的記憶體空間。這也就是為什麼可服用方法應該新增到建構函式的prototype屬性中的原因。

  向程式語言中新增便利的功能通常也稱之為語法糖。在這種情況下,method()方法也可以稱之為“糖方法(sugar method)”。

  使用method()定義類的方法形式如下:

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

  請注意建構函式是如何連線到method()的呼叫,其依次連線到下一個method()的呼叫,後面以此類推。這個例子遵循了前面介紹的鏈模式,它可以幫助您以單個宣告語句定義整個“類”。

  method()方法有兩個引數:新方法的名稱、方法的實現。

var a = new Person('Adam');
a.getName();
a.setName('Eve').getName();
// 再次強調,請注意鏈模式已經生效,這是因為setName()返回了this,從而使得以上程式碼可以正常執行。

// 最後,我們看一下method()方法是如何實現的:

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

  在method()的實現中,首先我們應該認真的檢查該方法是否已經實現過。如果沒有,那麼繼續新增函式,並將其作為implementation引數傳遞給建構函式的原型。在這種情況下,this指的是建構函式,其原型得到了增強。

 

  物件建立模式的內容到這裡就告一段落了,這一整章文章講解了名稱空間模式、宣告依賴、私有模式、模組模式以及沙箱模式、物件常量、鏈模式等一系列有用的建立物件的方法。那麼下一章,我們會學習下程式碼複用模式。很重要