0

I need to add some more OO flavor to my pure JS objects. Basically, I have on the server side

class Superitem {
    List<Item> items;
    Whatever whatever;
}

class Item {
    List<Subitem> subitems;
    Whatever whatever;
}

class Subitem {
    List<Whatever> whatevers;
}

In the client, I get a superitem as a plain Javascript hash and would like to convert it to something better. I started like

 Superitem(plain) {
      this.items = plain && plain.items || [];
      this.whatever = new Whatever(plain.whatever);
 }

but it's too verbose (my real classes are more complicated) and I rather doubt if its worth the effort. I'm not trying to mimic Java in Javascript, just want to add a few useful methods. Is there a better way? Thing like $.extend seem to be useless here.

maaartinus
  • 44,714
  • 32
  • 161
  • 320

2 Answers2

1

$.extend is hardly useless. You could define the constructor[s] like so:

function Superitem(data) {
    $.extend(this, { items: [] }, data);
    this.whatever = new Whatever(this.whatever);
}

$.extend will inject into this first the defaults ({ items: [] }) and then the plain object provided to the function. It then converts whatever to a Whatever.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • This sounds good, except that in the later steps I will possibly garble the original `data` (which may be needed somewhere). I guess making a deep copy of `data` at the very beginning solves it. – maaartinus Jun 29 '14 at 00:56
  • @maaartinus: Note that going through the structure, converting everything to an instance of one of your classes *is* a deep copy. In this case, since we didn’t touch `items` besides bringing it over, it isn’t a deep copy, but since we touched `whatever`, changing it would not affect the original `data`. – icktoofay Jun 29 '14 at 00:59
  • Yes, but this assumes I don't forget anything. As the next step I have to do something like `var self = this; $.each(self.items, function(i,v) {self.items[i] = new Item(v);}`, right? And check for `hasOwnProperty`, right? – maaartinus Jun 29 '14 at 01:07
  • @maaartinus: Indeed, it assumes you don’t forget anything. Doing a deep copy first would be safer. Case in point: you’d need to use `map` rather than `$.each`. If you put a `if(!(this isinstance Item)) return new Item(data);` at the top of the definition of `Item`, you could then rewrite that line as `this.items = this.items.map(Item);`. I don’t see where `hasOwnProperty` comes in if you’re providing defaults. – icktoofay Jun 29 '14 at 01:10
  • I mentioned `hasOwnProperty` because of `$.each` [iterating over everything](http://stackoverflow.com/questions/13688337/is-there-a-jquery-way-of-iterating-over-an-objects-own-properties-only) and I don't want to add any garbage. – maaartinus Jun 29 '14 at 01:18
  • @maaartinus: I’m guessing that only becomes a problem if you’re using it to iterate over something other than an array or you’ve touched `Array.prototype`. Either way, using `map` does not possess the same caveats, although it’s unavailable in older browsers (though can be shimmed; see es5-shim). – icktoofay Jun 29 '14 at 01:20
0

Object hashes as you say are already regular, normal objects.

jQuery's extend method works if you are trying to merge multiple properties/methods, but it isn't needed.

// Create an object through JSON, just to show its a regular
// object.
var obj = JSON.parse('{"prop" : true}');
obj.method = function() {alert(this.prop)};

obj.method();
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
  • But I don't want to add the method directly to all instances. This makes debugging much worse as the methods obfuscate the content. – maaartinus Jun 29 '14 at 00:53
  • Then you'll have to update your question and let us know what you *are* trying to add methods to. – Jeremy J Starcher Jun 29 '14 at 00:53
  • To the prototype. That's why I need to create the object via the constructor... at least I think so. Sorry for being imprecise. – maaartinus Jun 29 '14 at 01:03