2

I have a "class" that is essentially a beefed-up Array:

function NamedArray(name) {
  var result = [];
  result.name = name;
  return result;
};

var cheeses = new NamedArray('Cheeses');

This works great. What doesn't work is adding a prototype for this "class":

NamedArray.prototype = {
  nameInAllCaps: function() {
    return this.name.toUpperCase();
  }
};

cheeses.nameInAllCaps();
=> TypeError: Object #<Object> has no method 'nameInAllCaps'

My first thought was just to mix the "prototype" into the result Array:

function NamedArray(name) {
  var result = [];
  result.name = name;
  for (var prop in NamedArray.prototype) {
    if (NamedArray.prototype.hasOwnProperty(prop) {
      result[prop] = NamedArray.prototype[prop];
    }
  }
  return result;
};

This works, but it causes each instance to have its own copy of the prototype properties. Is there a way to insert NamedArray.prototype into the prototype chain of the result Array?

James A. Rosen
  • 64,193
  • 61
  • 179
  • 261
  • 2
    This question is a duplicate of this I think: http://stackoverflow.com/questions/5185122/prototypal-inheritance-question-in-javascript – idbentley Apr 08 '11 at 18:04
  • It's certainly very close. In this case, though, I'm not willing to merge things into the actual `Array.prototype` because I don't want them to show up for *every* `Array`, just `NamedArray`s. – James A. Rosen Apr 08 '11 at 18:26
  • I haven't figured out how to insert into the prototype chain for an instance, but I found another way around the problem: return the actual `NamedArray` instance and set `NamedArray.prototype = new Array();`. This gives `NamedArray`s full `Array`-like support! – James A. Rosen Apr 08 '11 at 18:59
  • Be forewarned however that commonly used versions of IE (such as 8 and possibly 9 [I haven't done a lot of checking on that version]) can act very, very oddly when you attempt to inherit from Array in this manner. I wouldn't recommend doing this if you require production-level stability for your project. In theory of course it works... but then there's Microsoft. – mr.stobbe Oct 15 '11 at 02:23
  • Check out http://stackoverflow.com/questions/2117614/subclass-prototype-new-superclass-vs-subclass-new-superclass and the second (but not "answered" for some reason) answer (Erik's) explains a bit of what's going on there when dealing with arrays. – mr.stobbe Oct 15 '11 at 02:34

1 Answers1

2

James,

The problem is that your "constructor" is returning something other than the newly-allocated object created by new. (Instead, you're creating an array from inside your constructor, and returning that.)

To correct this confusing aspect of your constructor code, consider something like:

function NamedArray(name) {
  this.name = name;
};

NamedArray.prototype = new Array();
NamedArray.prototype.nameInAllCaps =  function() {
  return this.name.toUpperCase();
}

c = new NamedArray("cheeses");
console.log(c.name);
console.log(c.nameInAllCaps());
Bosh
  • 8,138
  • 11
  • 51
  • 77
  • Works, but not everywhere. IE has problems with `prototype = new Array()` it in certain browsers (it'll look like it works with no errors, but then accessors don't work correctly). – mr.stobbe Oct 15 '11 at 02:28