15

I'm currently working with some data using Javascript that is in the form of an array. The array may contain an empty entry at the end, such as [1,2,]. In Google Chrome and Firefox, the length of that example would be 2; however, in IE, the length is 3.

In short: Internet Explorer is giving a different length for an array in Javascript than Google Chrome and Firefox. Is there a way to standardize this behavior across all browsers?

Code:

var a = [1,];
alert(a.length);

EDIT:

A lot of answers are saying not to have a trailing comma, however, the data is given to me in this way.

Ivan
  • 10,052
  • 12
  • 47
  • 78
  • possible duplicate of [Javascript Browser Quirks - array.Length](http://stackoverflow.com/questions/29053/javascript-browser-quirks-array-length) – mplungjan Jun 30 '11 at 21:27
  • @mplungjan: Definitely not a duplicate since I'm not just saying: "O look! A quirk!" I'm asking for a cross browser way to standardize the length. – Ivan Jun 30 '11 at 21:49
  • Which is given [here](http://stackoverflow.com/questions/29053/javascript-browser-quirks-array-length/29062#29062) - it also says "possible" ;) – mplungjan Jul 01 '11 at 07:43
  • See also [IE9 JavaScript array initialization bug](http://stackoverflow.com/q/6196641/357774) – Noyo Jul 30 '13 at 08:44

3 Answers3

18

NEVER have trailing commas in IE. Period.

That goes for ARRAYs too

Javascript Browser Quirks - array.Length

To handle your edit this works (tested in in IE8):

if (a[a.length-1]==null) a.length--; // or a.pop()

For a safer test, please look at the other suggestion on this page: Length of Array Differs In Internet Explorer With Trailing Comma - DEMO HERE

By the way, never heard the words elision or elided before - learn something new here every day

Community
  • 1
  • 1
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • I've only heard of that with objects, not with Arrays. – Ivan Jun 30 '11 at 21:15
  • I don't understand why this has plus 3 votes. The first five links lead to OBJECTS, not arrays. – Ivan Jun 30 '11 at 21:19
  • Because it does not matter where you have trailing commas, IE will puke as you see. No need to only think about this when it is {} type object and the very first entry in the search DOES have comments about the array too. But just in case I will add the search – mplungjan Jun 30 '11 at 21:21
  • Thanks for the second search, it helped me re-find my question: http://notes.susam.in/2010/06/js-array-length-and-trailing-comma.html – Ivan Jun 30 '11 at 21:27
  • Yes, that would be the _ideal_ solution. – Ivan Jun 30 '11 at 21:37
  • @Ivan - you realise that this solution will remove any trailing member whose value is *undefined* or *null*? – RobG Jul 01 '11 at 00:51
  • @mplungjan - if you change the test to `a.hasOwnProperty(a.length - 1)`, you'll have a much better answer. Still not as good as mine though. ;-p – RobG Jul 01 '11 at 01:42
  • @Rob Great - I voted your answer up. When will my suggestion fail? – mplungjan Jul 01 '11 at 06:49
  • @mplungjan - it will "fail" where the trailing members have been assigned a value of *null* or *undefined* or are *undefined*. An elision doesn't add a property value at all, so it should be a *hasOwnProperty* test (i.e. to see if the property exists, not whether it has a value) it's what *Array.prototype.filter* does. – RobG Jul 01 '11 at 13:11
  • @RobG thanks. @Ivan I have updated my answer with a demo of Rob's code. Perhaps worth taking a look at the prototype method used – mplungjan Jul 01 '11 at 14:13
9

No. IE incorrectly interprets a single trailing comma as an elision and adds one to the length when it shouldn't (ECMA-262 sect. 11.1.4).

Edit

To clear up the confusion here, IE treats a single trailing comma in an array literal (incorrectly) as an elision, which means it increments array's length property but does not create a property. In other words, given:

var a = [0,1,];

In IE, a.length is 3, but there is no property a[2]. So if an appropriate solution is to remove only elided members from the end of an array (which is likely the best solution if they are an issue), then:

function tidyTrailingElisions(array) {
  var i = array.length;
  while (!array.hasOwnProperty(--i)) {}
  array.length = ++i;
  return array;
}

will remove only elided members from the end of the array (that is, properties that don't exist), it will not remove them elsewhere, nor will it waste time iterating over the entire array (which can result in elided members being added as undefined). To add to Array.prototype:

Array.prototype.tidyTrailingElisions = function() {
  var i = this.length;
  while ( !this.hasOwnProperty(--i)) {}
  this.length = ++i;
  return this;
};

Note that this is how Array.prorotype.filter works, it doesn't iterate over elided members (it uses a hasOwnProperty test and removes any elided mebers as part of filtering the array).

RobG
  • 142,382
  • 31
  • 172
  • 209
4

Try removing empty elements:

a = a.filter(function(){return true});

Then it should work the same way in IE and other browsers.

Update: if the JS version is lower than 1.6, try this:

Array.prototype.clean = function() {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == undefined) {
      this.splice(i, 1);
      i--;
    }
  }
  return this;
};


a.clean()
Andy
  • 1,454
  • 17
  • 33
  • [JS 1.6](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter) so IE9+ – mplungjan Jun 30 '11 at 21:18
  • Thanks for actually answering my question: "Is there a way to standardize this behavior across all browsers?" – Ivan Jun 30 '11 at 21:25
  • Andy: Would that not be cleverer to clean from the end and stop when an element was found? – mplungjan Jun 30 '11 at 21:27
  • That may have undesired results, it will remove any array index that has not been created as a property anywhere in the array, so: `[,1,,2].filter(function(){return true}).length` is 2. – RobG Jun 30 '11 at 21:29
  • I do not believe that [,1,,2] is treated differently by any browser, ONLY [.......,] is. Waste of CPU to clean from the beginning – mplungjan Jun 30 '11 at 21:37
  • @mplungian - precisely. The suggested answer will remove elided members everywhere, not just at the end. Also, the suggested *clean* function is not an alternative to *filter* as it doesn't conform to what *filter* actually does. – RobG Jun 30 '11 at 21:45
  • While this is a great solution, I think mplungjan's solution is a lot simpler to implement since this method would require adding a chunk of code for `.clean()`. – Ivan Jun 30 '11 at 21:48