简体   繁体   中英

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. The item function is actually an instance of kendo.data.Model.define that is being given a template. documentation for 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.

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". But I have been explicitly told I should not use the "new" operator here, either. 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?

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 .

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/

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.

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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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