0

I've written a class trying to extend the native Javascript Array class with a custom class, let's call it MyClass. This is basically what it looks like:

class MyClass extends Array

  constructor: (obj) -> @push.apply @, obj

  first: -> @slice 0, 1

Instantiating the class is no problem. Running this in the console:

var myInstance = new MyClass(["1", "2"])
> ["1", "2"]
myInstance instanceof MyClass
> true
myInstance instanceof Array
> true

works as exptected.

The problem is that if I run:

myInstance.first()
> ["1"] // as expected
myInstance.first() instanceof MyClass
> false // not expected
myInstance.first() instanceof Array
> true

the returned value is no longer an instance of MyClass.

I've also tried @__proto__.first = @first in the constructor function and first: -> @slice.call @, 0, 1. But with no success.

Why doesn't myInstance.first() instanceof MyClass return true?

Johan Dettmar
  • 27,968
  • 5
  • 31
  • 28
  • 1
    I don't think extending Array will ever work properly (http://stackoverflow.com/q/3261587/479863), why are you trying to do it? – mu is too short Mar 18 '14 at 18:57
  • Basically this is only experimental, I wanted to see if it's possible. Instead of polluting the `Array` class, I wanted to rather augment my own class. – Johan Dettmar Mar 19 '14 at 09:47

1 Answers1

1

Why doesn't myInstance.first() instanceof MyClass return true?

Because first calls slice, and Array.prototype.slice does always return an Array. You will need to overwrite it with a method that wraps it in a MyClass again:

class MyClass extends Array

  constructor: (obj) -> @push.apply @, obj

  slice: () -> new MyClass super
  splice: () -> new MyClass super
  concat: () -> new MyClass super
  filter: () -> new MyClass super
  map: () -> new MyClass super

  first: -> @slice 0, 1

And notice that subclassing Array does not work.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks! That solves the issue! However regarding memory footprint, wouldn't `new MyClass super` consume a bit more memory? Also, thanks for the article link! – Johan Dettmar Mar 19 '14 at 09:34
  • Sure it will. However, you *want* more than an `Array` :-) – Bergi Mar 19 '14 at 15:25
  • Yep, I totally get that. My questions should have been phrased like this; is there a way to create a new instance once, instead of each time I use for example `slice()`? – Johan Dettmar Mar 20 '14 at 11:02
  • I don't understand, the purpose of `slice` is to return a different, new instance? Do you want it to mutate your instance? – Bergi Mar 20 '14 at 11:11
  • I'm out in deep water here, but I though `Array.prototype.slice` only modified the existing instance of an array, rather than creating a new instance. That's why I wondered if that was doable for a subclass of `Array` as well. Maybe I'm just confused :) – Johan Dettmar Mar 20 '14 at 11:33
  • 1
    No, it doesn't modify. All the other array methods that do mutate (like `sort`, `push`, `shift`, …) work on `MyClass` instances without problems. – Bergi Mar 20 '14 at 11:36