简体   繁体   English

Javascript:“扩展”没有实例的对象

[英]Javascript : “extend” an object without an instance

I have a situation where I have a large, complex object, and I need to re-use it somewhere else with SLIGHT modification (extended properties, etc) 我遇到的情况是我有一个大而复杂的对象,我需要在其他地方稍加修改(扩展属性等)来重复使用它

In an effort to improve the simplicity and re-usability, I thought I would try to "extend" the original object. 为了提高简单性和可重用性,我认为我会尝试“扩展”原始对象。 So it looks something like this ... 所以看起来像这样...

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

The library being used is Telerik's Kendo UI , and I am using their MVVM system. 正在使用的库是Telerik的Kendo UI ,而我正在使用其MVVM系统。 The item function is actually an instance of kendo.data.Model.define that is being given a template. item函数实际上是kendo.data.Model.define一个实例,该实例正在获得模板。 documentation for Kendo.data.Model.define Kendo.data.Model.define的文档

So this is used like ... 所以这就像...

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

This creates a new view model that can be bound to the page. 这将创建一个可以绑定到页面的新视图模型。 The underlying model has a lot of the behavior, so changing the view model itself does not risk overwriting or changing the underlying core. 基础模型具有很多行为,因此更改视图模型本身不会覆盖或更改基础核心。

This works fine. 这很好。 It moves the functionality I need into a separate file, and cleans up my bigger implementation. 它将所需的功能移到一个单独的文件中,并清理了较大的实现。 This is the expected use of the function as well, outlined by the documentation for the library I am using. 这也是该函数的预期用法,我正在使用的库的文档中对此进行了概述。

But then there is another model called schema , and it is basically identical to item except it has a few extra properties. 但是,还有另一个名为schema模型,除了具有一些额外的属性外,它与item基本上相同。

Rather than copy and paste the item model, I thought it was smarter to just try and extend it. 与其复制并粘贴项目模型,不如尝试扩展它会更聪明。 So I attempted this approach... 所以我尝试了这种方法

(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);

This does not work, though, because the path given is not an instance of "item". 但是,这不起作用,因为给定的路径不是“ item”的实例。 But I have been explicitly told I should not use the "new" operator here, either. 但是我被明确告知,我也不应该在这里使用“ new”运算符。 I simply want to "pull" the actual model from item over, and extend it. 我只是想从项目中“拉”实际模型,然后进行扩展。

Is there any way to do this? 有什么办法吗? Or is this beyond Javascript's capability? 还是这超出了Javascript的能力?

Update 更新

The code being used for the 'namespaces' is this; 用于“命名空间”的代码是这样;

(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));

Since your object contains nested objects, you'll want to use the deep extend. 由于您的对象包含嵌套对象,因此需要使用深层扩展。 To do that, add true as the first parameter to $.extend . 为此,将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/ http://jsfiddle.net/2Jw9L/

when you add kendoui, it becomes difficult (i won't say impossible, there's likely a way to do it that i haven't thought of) to extend it this way, and easier to just create an object outside of the modules and extend it. 当您添加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/ http://jsfiddle.net/MsrP6/9/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM