0

I have been struggling for too long over creating a function/object with inheritance. I think my problem lies in the fact that the function/object is created with a parameter. I have looked at all the examples of extending JavaScript function/objects here (including https://stackoverflow.com/a/10430875/489865 which effectively discusses part of my problem) and elsewhere but cannot find what I need.

Goal is to create and wrap XML objects "neatly". (The fact that it's to do with XML should not be relevant to the question/answer.) There will be some properties/functions common to all documents, plus some specific ones for different document instances. Here is skeleton of my code with comments:

// base common function/object for all XML documents
// creates an XML document by deserializing text
// and has a function for serializing to text
var XMLDoc = function (xmlText)
{
    this._xmlDoc = $.parseXML(xmlText);

    XMLDoc.prototype.serialize = function () { return serialized(this._xmlDoc); }
}

// extend base with a bunch of common functions
$.extend(XMLDoc.prototype, {
    doc: function () { return this._xmlDoc; },

    find: function (selector) { return $(this._xmlDoc).find(selector); }
});

// start defining specific-instance-methods
// *** I THINK THIS IS WHERE I AM GOING WRONG ***
var XMLDocInstance1 = XMLDoc;

// extend particular instance with specific methods
$.extend(XMLDocInstance1.prototype, {
    specific1: function () { ... }
});

// create specific instance
// I like this "new" way; note that XMLDocInstance1 takes a parameter
var xmlDocInstance1 = new XMLDocInstance1("<element1 />");

So far this seemed to work fine. Then of course I came to add another instance-specific:

var XMLDocInstance2 = XMLDoc;

$.extend(XMLDocInstance2.prototype, { ... });

var xmlDocInstance2 = new XMLDocInstance2("<element2 />");

Whereupon I discovered that xmlDocInstance2 has all of xmlDocInstance1's properties and vice versa...

I realise this is because the statement var XMLDocInstance1 = XMLDoc; means that XMLDocInstance1 is the same object as XMLDoc, and so my $.extend(XMLDocInstance1.prototype) is actually extending XMLDoc.prototype, which I don't want. I need XMLDocInstance1 to start out as some kind of copy of XMLDoc before I extend it.

I have tried all sorts of variations on extend (e.g. var XMLDoc = $.extend({}, XMLDoc;) ) without success. On a suggestion from somewhere, I tried var XMLDocInstance1 = new XMLDoc; (note not new XMLDoc()), which has the right "feeling" for getting a copy, but it still executes XMLDoc's body, which of course fails.

How do I achieve what I need? Am I going about it the wrong way? I would like to use $.extend() (rather than, say, Object.create()), but am open to other suggestions.

Community
  • 1
  • 1
JonBrave
  • 4,045
  • 3
  • 38
  • 115
  • *"I would like to use $.extend() (rather than, say, `Object.create()`)..."* Why? In ES5, `Object.create` is the right thing for this. – T.J. Crowder May 10 '17 at 09:46
  • OK, if you say that is the right way to go (so long as that works in IE 11). I _did_ try something with `Object.create()` and still got stuck, so might you be kind enough to show me a skeleton? – JonBrave May 10 '17 at 09:54
  • 1
    Hey presto, it works (if a touch ugly IMHO), thank you so much for swift answer! I had not come across that question in my searches; I wish I had asked this two days ago! Given that you have marked my question as duplicate, is there any point my editing it to show the solution using your approach? – JonBrave May 10 '17 at 10:14
  • 1
    Glad that helped! My instinct is probably not, normally answers don't go in questions, but really it's up to you. Re it being "a touch ugly" -- that's why we have `class` syntax now, it **was** a bit ugly. :-) – T.J. Crowder May 10 '17 at 10:28

0 Answers0