Potatoswatter
Potatoswatter

Reputation: 137790

inherit from Javascript Array or typed array

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

Answers (1)

Jim Fallin
Jim Fallin

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);
  1. Returns Real Array
  2. No Detection Issues
  3. Allows you to override everything you want and add custom properties and methods just like an inherited array.

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

Related Questions