Reputation: 137790
I want to make a JavaScript class vector
which is a zero-initialized array. I'll probably want to add math functionality later, but I don't want to sacrifice the memory or performance qualities of the native types because the program operates on a lot of data. (It's basically scientific visualization.)
To insert Array.prototype
in the prototype chain, I tried to use
vector.prototype = Object.create( Array.prototype );
Firefox gives me an error
TypeError: Array.prototype.toSource called on incompatible Object
Is this a bug in Firefox? It seems to work in Webkit.
So, I tried to use Float32Array
which is closer to what I want, and zero-initialized by default anyway.
var vector = function( size ) { Float32Array.call( this, size ); }
vector.prototype = Object.create( Float32Array.prototype );
In Firefox, this runs but new
doesn't initialize objects properly. In Webkit new vector
throws an exception. Makes no difference if I use vector.prototype = Float32Array.prototype
instead.
Am I fundamentally asking for too much?
Upvotes: 3
Views: 2018
Reputation: 236
It is nearly impossible to truly inherit from the JavaScript Array because of very special functionality that is built in to the language and how it handles arrays. You will see a ton of answers but most of them will fail under special circumstances. 1) if you inherit it, it will lose the special length properties. 2) if you use the __ ProtoType __ variable, it is non standard and will not work on all browsers. 3) There are many ways of detecting arrays in 3rd party libraries that might fail when checked. instanceof Array.isArray and ==['Object Array'] could all be used.
For more detailed reading, I would suggest this article How ECMA still does not allow to subclass array
I have a solution of returning a real array and avoiding all of these issues. Here is the fiddle Inhetit from JavaScript Array There are detection, length and functionality tests on the fiddle.
var ArrayGenerator = (function () {
var args = [].slice.call(arguments);
var Arr = new Array();
var ovevar ArrayGenerator = (function () {
var args = [].slice.call(arguments);
var Arr = new Array();
var overiddenPush = Arr.push;
args.forEach(function (arg) {
Arr.push(arg);
});
args = null;
Arr.push = function (args) {
overiddenPush.apply(this, arguments);
}
Arr.TableName = "YourTable";
return Arr;
});
//You initialize your array like this
var MyArray=new ArrayGenerator(1,2,3);
You simply create an array, store the original methods in internal variables and replace the public methods with you own. To call the base, you simple call your referenced methods instead of prototype like a regular inherited object.
Upvotes: 3