1

Is possible create a clone of the object Array? I do not want to extend the Array object itself because my specific methods should not be exposed for all the arrays of my app. Only a specific Arrays.

var Arr = function () {};
Arr.prototype = Object.create( Array.prototype );
Arr.prototype.push = function() {
    // Some custom code here
    Array.prototype.push.apply( this, arguments );
};

This example work well using methods, but if I set the values literally, the length is not incremented. Because Arr is an Object actually.

var arr1 = new Arr();
arr1[1] = 13;
console.log(Object.prototype.toString.call( arr1 ), arr1, arr1.length); // [object Object] { '1': 13 } 0

var arr2 = new Array();
arr2[1] = 13;
console.log(Object.prototype.toString.call( arr2 ), arr2, arr2.length); // [object Array] [ , 13 ] 2

1 Answer 1

3

In ES5 and earlier, you couldn't "subclass" Array (that is, create your own constructor and prototype based on the Array constructor and Array.prototype) and get correct handling for the magic properties, but as of ES2015 (aka "ES6"), it's possible in a couple of different ways, the easiest being the new class stuff:

// REQUIRES ES2015+!
class MyArray extends Array {
    constructor(...args) {
        super(...args);
    }

    lengthTimesTwo() {
        return this.length * 2;
    }

    cappedJoin() {
        return this.map((s) => s.toUpperCase()).join();
    }
}

var a = new MyArray("one", "two", "three");
console.log("lengthTimesTwo: " + a.lengthTimesTwo());
console.log("cappedJoin: " + a.cappedJoin());

In the ES5 world, there are hoops you can jump through to get really close, and people building transpilers like Babel do (if you're stuck targeting ES5 environments, you might want to use class and transpile), but most of the time it's good enough to create a function that builds an array and then adds methods just to that specific instance:

var arrayExtras = {
  lengthTimesTwo: function() {
    return this.length * 2;
  },
  cappedJoin: function() {
      return this.map(function(s) {
        return s.toUpperCase();
      }).join();
    }
    //...and so on...
};

function myArray() {
  var key, rv = [];
  rv.push.apply(rv, arguments);
  for (key in arrayExtras) {
    Object.defineProperty(rv, key, { // Add the method as a non-enumerable property
        value: arrayExtras[key],
        writable: true
    });
    // For pre-ES5 support, change the call above to simply:
    // rv[ley] = arrayExtras[key];
  }
  return rv;
}

var a = myArray("one", "two", "three");
console.log("lengthTimesTwo: " + a.lengthTimesTwo());
console.log("cappedJoin: " + a.cappedJoin());

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

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.