2013-12-09 58 views
2

我有一個情況我有一個大型的,複雜的對象,我需要稍作修改(擴展屬性等)的Javascript:「擴展」的對象,而一個實例

在別的地方重新使用它爲了提高簡單性和可重用性,我想我會盡量「擴展」原始對象。所以它看起來是這樣的......

(function ($, window) { 
    website.module('admin.models', function (exports, require) { 
     exports.item = { 
        // large, complex object that will be instantiated by other things 
      }; 
    }); 
})(jQuery, window); 

正在使用的庫是Telerik的Kendo UI,和我使用他們的MVVM系統。 item函數實際上是一個kendo.data.Model.define的實例,它被賦予一個模板。 documentation for Kendo.data.Model.define

因此,這是用來像...

var item = new website.admin.models.item({ 
    // specific property values 
}); 

這將創建一個可以綁定到該頁面的新視圖模型。底層模型具有很多行爲,因此更改視圖模型本身不會冒險覆蓋或更改底層核心。

這工作正常。它將我需要的功能移到一個單獨的文件中,並清理了我的更大的實現。這也是該函數的預期用法,由我正在使用的庫的文檔概述。

但是接下來還有另外一個叫做schema的模型,它基本上和item一樣,只是它有一些額外的屬性。

與其複製和粘貼項目模型,我認爲試試並擴展它是明智的。所以我嘗試了這種方法......

(function ($, window) { 
    website.module('admin.models', function (exports, require) { 
     exports.schema = $.extend({ 
       Item: { 
        Id: null, // will be filled in on the UI 
        Name: null, // will be filled in on the UI 
        Description: null, // will be filled in on the UI 
        Timestamp: null // will be filled in on the UI 
       }, 
       Editing: false 
     }, website.admin.models.item); 
    }); 
})(jQuery, window); 

雖然這不起作用,因爲給出的路徑不是「item」的實例。但是我明確告訴我不應該在這裏使用「新」操作符。我只是想從項目中「拉」出實際的模型,並將其擴展。

有沒有辦法做到這一點?還是超越Javascript的能力呢?

更新

用於'命名空間'的代碼是這個;

(function (global) { 
    var globalNamespace = global['website']; 
    var VERSION = '3.0.1'; 

    function Module() { } 

    function numeric(s) { 
     if (!s) { 
      return 0; 
     } 
     var a = s.split('.'); 
     return 10000 * parseInt(a[0]) + 100 * parseInt(a[1]) + parseInt(a[2]); 
    } 

    if (globalNamespace) { 
     if (numeric(VERSION) <= numeric(globalNamespace['VERSION'])) { 
      return; 
     } 
     Module = globalNamespace.constructor; 
    } else { 
     global['website'] = globalNamespace = new Module(); 
    } 
    globalNamespace['VERSION'] = VERSION; 

    function require(path) { 
     path = path.replace(/-/g, '_'); 
     var parts = path.split('.'); 
     var ns = globalNamespace; 
     for (var i = 0; i < parts.length; i++) { 
      if (ns[parts[i]] === undefined) { 
       ns[parts[i]] = new Module(); 
      } 
      ns = ns[parts[i]]; 
     } 
     return ns; 
    } 

    var proto = Module.prototype; 

    proto['module'] = function (path, closure) { 
     var exports = require(path); 
     if (closure) { 
      closure(exports, require); 
     } 
     return exports; 
    }; 

    proto['extend'] = function (exports) { 
     for (var sym in exports) { 
      if (exports.hasOwnProperty(sym)) { 
       this[sym] = exports[sym]; 
      } 
     } 
    }; 
}(this)); 
+0

你能給的那種鍵/值是在'website.admin.models.item'的例子? –

+0

難道你不能導出和使用你創建的'var item'?如果是這樣,爲什麼不使用繼承,如'exports.schema = Object.create(item);',然後將屬性添加到'exports.schema'? –

+0

當然,我更新了代碼以顯示它,它位於exports.schema部分。將會有大約16個。但是「項目」代碼的其餘部分不需要有任何不同。只是...有一些新的屬性。 – Ciel

回答

1

由於您的對象包含嵌套對象,因此您需要使用深度擴展。爲此,請將true作爲$.extend的第一個參數。

exports.schema = $.extend(true, { 
    Item: { 
     Id: null, // will be filled in on the UI 
     Name: null, // will be filled in on the UI 
     Description: null, // will be filled in on the UI 
     Timestamp: null // will be filled in on the UI 
    }, 
    Editing: false 
}, website.admin.models.item); 

http://jsfiddle.net/2Jw9L/

當您添加kendoui,就很難(我不會說不可能,有可能是一個辦法做到這一點,我沒有想到的)以這種方式擴展它,並且更容易在模塊之外創建對象並對其進行擴展。

var theObj = { 
    ... 
}; 

(function ($, window, kendo) { 
    ehrpg.module('admin.models', function (exports, require) { 
     exports.item = kendo.data.Model.define($.extend(true,{},theObj)); 
    }); 
})(jQuery, window, kendo); 

(function ($, window, kendo) { 
    ehrpg.module('admin.models', function (exports, require) { 
     exports.schema = kendo.data.Model.define($.extend(true,{ 
      Item: { 
       Id: null, 
       Name: null, 
       Dirty: false, 
       Timestamp: null 
      } 
     },theObj)); 
    }); 
})(jQuery, window, kendo); 

http://jsfiddle.net/MsrP6/9/

+0

是的,是的,有一千次是的。這絕對是完美的。這可以讓我保持大量的重複代碼,所以當我必須執行維護時,我不會嘗試在幾個不同的文件之間連接點!非常感謝,我很高興這是可行的。我知道Javascript並不是真正的「OOP」語言,我儘可能地避免了OOP傾向,但有時他們更有幫助。 – Ciel

+0

奇怪。 'website.admin.models.item'是一個功能...但它不是。另一種選擇是使用繼承,如果對'... item'進行修改,則可能(或可能不需要)繼承。 –

+0

我不確定你的意思是繼承。我以爲JavaScript沒有繼承? – Ciel

相關問題