0

I have created an array like prototype:

function METracker() {}
METracker.prototype = Object.create(Array.prototype);
METracker.prototype.myMethod = function(aStd) {
    return true;
};

now i create an instance:

var aInst = new METracker('a', 'b', 'c');

Now I want to clone it so I do:

var cloneInst = aInst.slice();

however cloneInst no longer has the method .myMethod is there a way to keep the prototype on the clone?

Thanks

7
  • 3
    It is because slice returns an Array object, not METracker object and Array object doesn't have myMethod. Commented Mar 15, 2016 at 6:03
  • Thanks, I was trying to get slice to return METracker is this possible? Commented Mar 15, 2016 at 6:04
  • 1
    Unfortunately, nope, unless you can change the slice function itself. Otherwise, you need to build your own slice wrapper on METracker, which would slice and return a METracker instance. Commented Mar 15, 2016 at 6:07
  • Ah drats, makes sense. Could you please show how to build a slice wrapper. Commented Mar 15, 2016 at 6:08
  • 1
    Note that you can't "subclass" Array this way since instances must have the special, self–adjusting length property, and only Array instances have that. You can't emulate it. Commented Mar 15, 2016 at 6:16

2 Answers 2

1

If you're going to create your own array-alike, the trick is to extend an array instance, not the array prototype:

function MyAry() {
    var self = [];

    [].push.apply(self, arguments);

    // some dark magic

    var wrap = 'concat,fill,filter,map,slice';
    wrap.split(',').forEach(function(m) {
        var p = self[m];
        self[m] = function() {
            return MyAry.apply(null, p.apply(self, arguments));
        }
    });

    // add your stuff here

    self.myMethod = function() {
        document.write('values=' + this.join() + '<br>');
    };

    return self;
}


a = new MyAry(11,44,33,22);
a.push(55);
a[10] = 99;
a.myMethod()

b = a.sort().slice(0, 4).reverse();
b.myMethod();

Basically, you create a new array (a normal array, not your object), wrap some Array methods so that they return your object instead of generic arrays, and add your custom methods to that instance. All other array methods and the index operation keep working on your object, because it's just an array.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks georg very much this works absolutely superb!
1

I have created an array like prototype:

No, you haven't.

function METracker() {} METracker.prototype = Object.create(Array.prototype); METracker.prototype.myMethod = function(aStd) { return true; };

The METracker constructor does nothing at all, it will just return a new Object with Array.prototype on its [[Prototype]] chain.

var aInst = new METracker('a', 'b', 'c');

Just returns an instance of METracker, it has no data since the constructor doesn't do anything with the arguments passed. Assigning Array.prototype to the inheritance chain doesn't mean the Array constructor is invoked.

var cloneInst = aInst.slice();

Note that callling slice() on aInst just returns a new, empty array. aInst doesn't have a length property, so the algorithm for slice has nothing to iterate over. And even if aInst had properties, slice will only iterate over the numeric ones that exist with integer values from 0 to aInst.length - 1.

If you want to create a constructor that creates Array–like objects, consider something like:

function ArrayLike() {
  // Emulate Array constructor
  this.length = arguments.length;
  Array.prototype.forEach.call(arguments, function(arg, i) {
    this[i] = arg;
  }, this);
}

ArrayLike.prototype = Object.create(Array.prototype); 

var a = new ArrayLike(1,2,3);
document.write(a.length);
document.write('<br>' + a.join());

The above is just play code, there is a lot more to do. Fixing the length issue isn't easy, I'm not sure it can be done. Maybe there needs to be a private "fixLength" method, but methods like splice need to adjust the length and fix indexes as they go, so you'll have to write a constructor that emulates the Array constructor and many methods to do re–indexing and adjust length appropriately (push, pop, shift, unshift, etc.).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.