0

I'm quite confused by these little guys. After I encountered some funny behavior between them and Array.prototype.filter I fooled around in re.pl trying to understand their true value. But it seems like they switch from <empty> to undefined depending on who's looking (at least in re.pl and node, they're logged as undefined in this environment).

 
    let emptyArr = new Array(5);
    //set up two control elements
    emptyArr[0] = 0;
    emptyArr[4] = undefined;
    
    
    console.log('\nemptyArr:', emptyArr)
    console.log('\npeeking at an empty element:', emptyArr[1])
    console.log('\nfilter for undefined elements:', emptyArr.filter(e => e === undefined))
    console.log('\nfilter for any element:', 
       emptyArr.filter(e => {
          console.log("ele:", e)
          return true
       })
    ) // only two elements are registered here

    console.log('\nmappedEmpty:', emptyArr.map(e => e)) //everything is preserved

    console.log('\ngenerated array', Array.from(emptyArr)) 
    console.log('\nalways true filter on generated array:', Array.from(emptyArr).filter(e => true)) // empties are now 'true' undefined

What's the story here? Quirky array prototype methods or a secret ultra-false-y value?

1
  • <empty> entries are missing key–value entries in an array. An undefined entry is just a key with the value undefined, but <empty> does not even have a key. Commented Oct 12, 2017 at 18:55

3 Answers 3

2

What's the story here? Quirky array prototype methods or a secret ultra-false-y value?

Arrays are objects. Elements of the array are simply properties of the underlying object. Accessing a property that doesn't exist returns undefined. Therefore when you access emptyArr[1] you get undefined. Looking at the console of Chrome might help:

enter image description here

As you can see, 0 and 4 exist because you created those entries by assigning to them. 1, 2 and 3 don't exist.

These positions with no value are often referred to as "holes". Your array has holes at positions 1, 2 and 3. An array with holes is also called "sparse array".

Most array methods (.filter, .map, etc) skip over holes. We can easily prove this for some methods:

// Array#map
console.log([,,,42].map(() => 21)); // [,,,21], not [21,21,21,21]
// Array#every
console.log([,,,42].every(x => x === 42)); // true, not false

Of course we could also just look at the language specification, where it says for Array#every for example:

callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.

Array.from on the other hand explicitly looks at the .length property of the value passed to it and it will copy any property/element between 0 and .length. In other words, it does not skip holes.

Look at the difference between the arrays in the Chrome console:

enter image description here

Worth noting maybe that arr.length doesn't care about holes. It will always be the highest set index in the array + 1.

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

Comments

0

Well actually they do not exist. Imagine arrays being objects, using new Array(5) you will get:

{
 length:5
}

So like objects they return undefined for nonset values:

array[3] // undefined

But that doesnt mean theres a property set to undefined. That changes when you use Array.from . You can imagine it doing sth like

for(var i = 0; i < oldarray.lemgth; i++){
 newarray[i] = oldarray[i];
}

So after the Array.from call itll look like this:

{
length:5,
0:undefined,
1:undefined,
2:undefined,
3:undefined,
4:undefined
}

Comments

0

They are undefined. It just depends on the engine how it displays them, but trying to access them returns undefined, because that's what they are - elements that have not been defined.

For example the Chrome console will print > (5) [empty × 5] while node prints [ , , , , ] for the same new Array(5). It's just a more visual representation than, say, showing [undefined, undefined, undefined, undefined, undefined].

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.