65

Arrays have a "length" property by default.

Can I add custom properties to them?

Without having to make them objects.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ellabeauty
  • 2,529
  • 3
  • 21
  • 25
  • 6
    what do you mean by *"add custom properties without having to make them objects?"* Arrays ARE objects. Just about everything in JS is an object. And what are these properties? Can you explain further? – Joseph Mar 31 '12 at 01:10
  • They **are** objects. Just a special kind of objects. Like functions for example which are a special kind of objects, too. – ThiefMaster Mar 31 '12 at 01:15
  • See also [this related question](http://stackoverflow.com/questions/24730145/what-are-the-drawbacks-of-setting-string-properties-on-arrays) for why you shouldn't do this. – Ja͢ck Jul 14 '14 at 07:14

5 Answers5

76
var arr = [1,2,3,4,5];
arr.prop = 'value';

Arrays are already objects in JavaScript -- they just have some extra features and special literal syntax.

Team3537
  • 51
  • 5
Kevin Ennis
  • 14,226
  • 2
  • 43
  • 44
  • will my property be iterated with the rest of the elements? because in console.log I don't see it with opaque text like "length" – ellabeauty Mar 31 '12 at 01:12
  • 11
    They will be iterated when you use `for(var key in arr)`. But that's something you shouldn't use on arrays anyway, so it shouldn't be a problem for you. A `for(var i = 0; i < arr.length; i++)` iteration will not include those properties (they do not even add to the length of the array) – ThiefMaster Mar 31 '12 at 01:16
  • 2
    if you use a `for in` loop, the property will be iterated. In a regular `for` loop, it won't be -- since you'd only be accessing each member by its array index. It also won't be iterated by native array ES5 methods like `forEach`. – Kevin Ennis Mar 31 '12 at 01:17
  • 3
    The above is all true. For instance, `stringName.match(/regex/)` returns an array, however the array also has two extra properties attached to it for your reference - "The returned Array has an extra input property, which contains the original string that was parsed. In addition, it has an index property, which represents the zero-based index of the match in the string." But, when you iterate over what is returned, or when you `console.log` the result, the result set doesn't contain the extra properties, just the elements of the array itself. – CtheGood Oct 08 '15 at 21:47
  • 2
    console.log will show the properties, also if you want to access just the properties. you can do `keys = Object.keys(arr).slice(arr.length);`. Then you can iterate over just the keys using `for in` **NOTE** however that when you assign properties to an array you should avoid using `Numbers` only since they will be interpreted as array indexes. I.E. (`arr['7']` will be confused with `arr[7]` if your object inherits from `Array`) – Leathan Aug 10 '17 at 12:37
45

As other answers state, it's perfectly possible, because arrays in JavaScript are just objects. However, there is still the a question of whether it's a good idea or not.

That's a "coding style" question, so it's hard to say objectively, but Douglas Crockford doesn't have a problem with it (at least in some cases). In JavaScript: The Good Parts, he actually uses the example of adding a "total" method to an array.

Because an array is really an object, we can add methods directly to an individual array:

// Give the data array a total function

data.total = function () {
    return this.reduce(add, 0);
};

total = data.total();    // total is 108

Since the string 'total' is not an integer, adding a total property to an array does not change its length.

(p62, Crockford's "JavaScript The Good Parts", found on Google Books)

However, it is worth mentioning that these extra properties are not included in JSON serialisation, and would be thrown away if you do anything like arr = arr.slice(1);.

cloudfeet
  • 12,156
  • 1
  • 56
  • 57
  • Thanks for including references. – Tyler Collier Jan 29 '15 at 17:51
  • 2
    Also, if the array goes through any of its prototype methods (map, filter, etc.) the property won't be transferred to the new array, since the method was put on an instance of `Array`. Probably expected but maybe not desirable in this case? – Daniel Lizik Jan 26 '16 at 15:59
  • The built in `RegExp.prototype.exec()` returns arrays like this. Try `.exec()` and you get back an array like `[, , ..., index: , input: ]`. See [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec). – tjfwalker Jan 31 '19 at 05:07
8

If you meant to hide it in an Array, etc. (at least that's what I was looking for):

Object.defineProperty( targ, "myVal", { enumerable: false, writable: true } );

Then the array doesn't add it to length, so it's a property, not a value I guess you could say.

Then if you want to see the keys in an object for instance, Object.keys won't see it, but Reflect.ownKeys() will.

The Reflect version of defineProperty will return success or fail, while Object's returns the object passed.

Remember Reflect.preventExtensions() will (like it says) stop you or others from extending them.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Master James
  • 1,691
  • 15
  • 19
4

Arrays are objects and therefore you can add your own properties to them:

var arr = [1, 2, 3];
arr.foo = 'bar';

Extending from other answers, here are the following ways of iterating over the array, excluding custom properties.

  1. Using a standard for loop

    for (let i = 0; i < arr_length; i++)
        console.log(arr[i]);
    

    or if not using ES6:

    for (var i = 0; i < arr.length; i++)
        console.log(arr[i]);
    
  2. Using the for ... of loop (ES6+)

    for (let el of arr)
        console.log(el)
    
  3. Using Array.prototype.forEach (ES6+)

    arr.forEach(el => console.log(el));
    

    or

    arr.forEach(function(el) {
        console.log(el);
    });
    

Iterating over the array, including all properties (e.g., custom properties, length):

for (let prop in arr)
    console.log(prop);

Or if not using ES6:

for (var prop in arr)
    console.log(prop);
xxx
  • 1,153
  • 1
  • 11
  • 23
David Callanan
  • 5,601
  • 7
  • 63
  • 105
2

Yes. You can add them to the object by just declaring them and you can also extend Array using Array.prototype

var j = new Array();
j.yourprop = "foo";
Bakudan
  • 19,134
  • 9
  • 53
  • 73
Dave Thomas
  • 3,667
  • 2
  • 33
  • 41