If you've never read Kyle Simpson's fantastic series, You Don't know JS, I'd first encourage to stop reading this, go read that , and then come bac...
For further actions, you may consider blocking this person and/or reporting abuse
I generally don't concern myself too much with what's happening under the hood; but this was interesting :)
So - the output of this is enlightening:
The implicit/explicit
undefined
looks like a red herring to me.Array properties that haven't been explicitly declared are simply not set as enumerable; but I guess as far as the interpreter is concerned the values to be iterated over have been defined:
Also, see the output from
console.log(array1.entries().next())
.Yep. Beat me to it. It's all the difference between having an ownProperty or not.
I'm wondering, since I've never tried to do this and can't conveniently try it right now, what the
in
operator reports for things like0 in [,1,2]
? Is that statement true or false? Or is it a syntax error?I tested five loops:
for in
,for of
,forEach
,map
andfor of
was the only one that iterated on all slots.Here's a gist of what I wrote. Feel free to run it in a few different browsers and tell me if my tests were wrong.
I went ahead and updated my test gist with an
if in
test to see what it did.it, too, will inform us that only an index of
2
exists. This I think further confirms that these items in the array are not "hidden properties" at all.You make a great argument, but I don't think it's a red herring. (I'm more than willing to be proven wrong, though).
I read your comment a few times and wondered, "If a property isn't explicitly declared, does that mean it's implicitly undefined?" i.e.... are we really saying the same thing?
I decided to dig into the specs to see if a property really is created, though. And I don't think one is.
I've found at least one spot in the ecma specs that defines this behavior in section 12.2.5:
When you say
At least in this one section, it doesn't appear as though these empty slots are properties created on the array.
Most telling is step 8 of 22.1.3 of the specs that describe how an array is created:
So,
Pk
is the key, anditemK
is the value. If you have an array containing anundefined
, e.g.[undefined, 1, 2]
, it's an item ... at least I think ... according this logic.Similarly, that would mean that in the case of
[,1,2]
, there is no "item" in the first slot.But that all depends on what
CreateDataProperty
does. When I read howCreateDataProperty
behaves, in section 7.3.4, steps 3 and 4 don't give a condition for setting theenumerable
prop in the descriptor tofalse
:So, if there were a value... any value, it would be enumerable. But if there isn't a value... it's not.
So I think "implicit undefined" is an accurate description of this case because the specifications dictate in at least one place that "elided array elements are not defined" ... meaning no properties are created on the array and browser implementers have to give you something if you ask for a value at a slot that has no value. So the Array internals are giving you
undefined
.I think.
Like I said - this isn't something I tend to dig into too much...
But I think we're more or less in agreement - I'm just not comfortable with the idea of a distinction between explicit/implicit undefined. However you get to it
undefined === undefined
:DI didn't dig into the spec but did think to do this:
So the above suggests that:
for ... of
assumes that Object.keys should conform to array standards (i.e. start at 0 increment by 1)for
loop just does what you tell it :)undefined
is always returned when you try to access an object property that doesn't existThanks for the article! It turns out that thinking about what happens under the hood can consume far too much of my time :D
I updated my article to reflect our conversation (seemed too useful not to)
I think this goes back to an odder quirk of JavaScript where sometimes
undefined
also means "undeclared", but not always.this "implicit undefined" is really more like an "undeclared", but JavaScript doesn't provide a means to distinguish the two very easily.
Oh - and a massive +1 for recommending the "I don't know JS" series!
I think this actually makes perfect sense if you actually take a look at the
documentation. When you set something to undefined you are initializing it. So while it is still undefined its not the same as uninitialized. Array.forEach isn't invoked on uninitialized values and for... in(which you shouldn't use with arrays anyways) does something similar(more specifically it will loop over enumerable properties). What you are referring to as implicitly undefined and explicitly undefined is largely just initialized and not initialized.
You are absolutely right on all points (and that's really what I was getting to).
The behavior makes sense once you break down what's actually going on (as is almost always the case with JavaScript)
And yeas, "implicitly undefined" and "explicitly undefined" could also be called "uninitialized" and "initialized". Though I like implicit/explicit because it suggests intent a bit more clearly.
Wow, great write up. Made me actually laugh out loud.
If I didn't already love JavaScript, I would steer clear. It sounds like a language somebody conceived of and implemented in like ten days with no forethought or planning.
Reminds me how relevant Douglas Crockford's "JavaScript, The Good Parts" still is.
Thank you!
I think JavaScript is brilliantly well done. Regardless of the whole, "10 days and no forethought", I think Brendan Eich did a lot right.
I think he understood way better than many other programmers how important it is in the browser to have a fault tolerant language that does as much as possible to prevent the UI from crashing on a user.
I think most of the "quirks" or "weirdnesses" in JavaScript can be explained as being quite intentional because Eich was trying to make a language that wouldn't punish the end user for the developer's mistakes.
Except
Date
.and
NaN !== NaN
.Those I think he screwed up on.
Ha, indeed. I think you're right.
I haven't done any testing, but the part where you go over array instantiation and c++, I wonder how smart the V8 engine is when it comes to allocate memory for an array. I know that you shouldn't use sparse arrays, inserting items at indexes so there's a gap, but I can't recall if it does optimizations based on setting a predefined array size
If I were smart enough to work on the V8 engine, I'd have it optimized based on array size.
Granted, I only ever took one C++ class... and I have liberal arts degrees. So I'm far from qualified-enough to say for sure if that's the right way to go.
whooaa... dang you Array 😂😂