6

In JavaScript when you define an array using the literal syntax, array elements may be omitted by using additional commas:

a = [1, 2, 3];   // 1, 2, 3
b = [1, , 2, 3]; // 1, undefined, 2, 3

I noticed that when accessing the values that the omitted values were not "own properties"

b.hasOwnProperty(1); //false

In contrast, if you define an array explicitly setting undefined, it will be set as an "own property":

c = [1, undefined, 2, 3];
c.hasOwnProperty(1); //true

Is the behavior for how omitted array elements are assigned defined in a spec? If so, which spec and where?

(optional bonus) Is it reliable cross-browser, such as evidenced by compatibility tables?

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • It's in the spec. http://es5.github.io/#x11.1.4 *"Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the element list is not preceded by an AssignmentExpression (i.e., a comma at the beginning or after another comma), the missing array element contributes to the length of the Array and increases the index of subsequent elements. Elided array elements are not defined. If an element is elided at the end of an array, that element does not contribute to the length of the Array."* –  May 09 '16 at 17:50
  • 1
    Or in the current spec: http://www.ecma-international.org/ecma-262/6.0/#sec-array-initializer – nils May 09 '16 at 17:54
  • @squint, I saw that particular quote, but it didn't say whether implementations were expected to implement it as a missing element, or as an element set to `undefined`. At least so far as I understood it. – zzzzBov May 09 '16 at 17:56
  • 2
    *"Elided array elements are not defined"* would need to mean that the property is not created, because of the definition of an [*array element*](http://es5.github.io/#array-element): *"A property whose property name is an array index is also called an element."* So a "not defined" element is saying that the property name is not defined as opposed to being defined with a default value. –  May 09 '16 at 18:01
  • ...as far as cross browser, the only array comma issues I can think of were in older IE where a trailing comma was supposed to be ignored but instead it added to the length of the array. Don't remember exactly which version fixed it, but definitely not later than IE9. –  May 09 '16 at 18:03
  • @squint, good catch on the "elided array elements are not defined", I'd managed to somehow read that as "elided array elements are undefined", which has different implications. – zzzzBov May 09 '16 at 18:04
  • @downvoter, care to comment on which part of the question was unclear or not useful? – zzzzBov May 09 '16 at 18:06
  • 3
    Yeah, gotta love JS... "not defined" !== "undefined" but looking up something "not defined" will give you "undefined"! Seems like a reasonable question, and I couldn't find a dupe right away, so +1. –  May 09 '16 at 18:09
  • @Bergi, I'm asking specifically for spec references with this question. However accurate the answers to those other questions may have been, none appeared to include references to where the behavior was defined. – zzzzBov May 09 '16 at 19:03
  • @zzzzBov: I see. Not sure whether that's off-topic "*trying to find an off-site resource*", but I can post an answer. – Bergi May 09 '16 at 20:10
  • @Bergi, I wondered about that a bit myself, but spec clarification tends to be on-topic. I'd planned to post an answer later if no one else had pinned down the details by then. – zzzzBov May 09 '16 at 20:17
  • @zzzzBov: Hm, spec clarification is on topic, but you didn't really ask for a clarification, rather "*Is there a spec?*". I can't believe you didn't know about ES, so maybe you can adjust your question. – Bergi May 09 '16 at 20:30
  • @Bergi, when I asked I wasn't sure if there was an actual defined behavior for this particular detail, or whether it was up to browser vendors, hence the "is there a spec?" Even with the quote saying that the "elided array elements are not defined" I wasn't particularly happy with that as an answer. In the end, the syntax details described explicitly how elided indices behave, it just took me a while to grok it. – zzzzBov May 09 '16 at 20:36

2 Answers2

3

Is the behavior for how omitted array elements are assigned defined in a spec?

Yes.

If so, which spec

The ECMAScript specification. At least in revisions 3, 5, 5.1 and 6.

and where?

In the semantics of array literal expressions, given by the Array Initializer section (ES5, ES6). It says

[…] the missing array element contributes to the length of the Array and increases the index of subsequent elements[, but they] are not defined.

In the evaluation of the expressions, they are simply skipped - they're counted but do not create a data property on the array instance, contrary to the assignment expressions that create the elements.

Is it reliable cross-browser?

Yes, even old Internet Explorers do it. The only quirks is that they count a trailing comma as an elision, which it should be not, and get the .length wrong.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

Do elided array elements ever produce an own property?

From squint's comment, which sourced a document on Annotated ECMAScript 5.1,

Elided array elements are not defined.

Note that this doesn't mean undefined. So no, the elided element isn't defined and so hasOwnProperty() returns false.

Community
  • 1
  • 1
8protons
  • 3,591
  • 5
  • 32
  • 67
  • I'm not clear on how this answers my question at all. `hasOwnProperty` does a cast to string, which is why I didn't bother using `b.hasOwnProperty('1')`. Note that `[undefined]` will have a single element that is an own property. `undefined` as a value has nothing to do with the status of a property being an own property. – zzzzBov May 09 '16 at 18:08
  • @zzzzBov I updated my answer to be more explicit right before you commented :] I checked quit a bit for any documentation that says `hasOwnProperty` "does a cast to string" but found nothing that defended that. Would you mind providing me with a source? The only sources I find that comment on this explicitly say that the parameter is a `string`. Thanks! – 8protons May 09 '16 at 18:37
  • 1
    @8protons: [The spec](http://es5.github.io/#x15.2.4.5) defines it to coerce its parameter to a string as its first step. –  May 09 '16 at 18:39
  • @squint Oh okay. Then why is the OP doing a comparison to `1`? How is `1` a property of an object? – 8protons May 09 '16 at 18:41
  • 1
    Arrays are just fancy objects; their indices are properties on the object. So `b[1]` is the same as `b["1"]`, setting aside questions of optimizations. If you did a `for-in` loop on an Array *(which isn't advisable in the regular case)*, the "indices" will be delivered as strings. `var b = ["foo", "bar"]; for (var key in b) console.log(key, typeof key);`. So `b` is an object with two properties, "0" and "1". –  May 09 '16 at 18:44
  • @8protons, I think you may be misunderstanding the intent of `b.hasOwnProperty(1)`. The intent is to check if `b[1]` (which returns a value of `undefined` (which represents no value (meta discussions are difficult))) is an "own property", which [has very specific meaning](https://es5.github.io/#x4.3.30). Referencing MDN (*not MSDN*) is not an appropriate source for this particular answer given the nuance I'm looking for. – zzzzBov May 09 '16 at 18:45
  • Thanks for the clarification! – 8protons May 09 '16 at 18:57