Reputation: 37298
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
Upvotes: 0
Views: 89
Reputation: 215029
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.
Upvotes: 1
Reputation: 147483
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.).
Upvotes: 1