Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do map, every, and other array functions skip empty values?

Tags:

javascript

Background

I was writing some code to check if 2 arrays where the same but for some reason the result was true when expecting false. On closer inspection I found that where array values where undefined they were skipped.

Example

const arr1 = [, , 3, 4]
const arr2 = [1, 2, 3, 4]
const result = arr1.every((item, index) => item === arr2[index])
console.log(result) // true (HOW????)

What I've tried

So I spent some time trying to get the value in here correctly but the only thing I've come up with is a regular for loop that makes iterations based on array length not the actual items.

Question

Why does this happen and is there a way to recognise these empty/undefined values in my array?

like image 542
Joe Lloyd Avatar asked Aug 07 '19 12:08

Joe Lloyd


People also ask

Can a map return null?

A map key can hold the null value. Adding a map entry with a key that matches an existing key in the map overwrites the existing entry with that key with the new entry. Map keys of type String are case-sensitive. Two keys that differ only by the case are considered unique and have corresponding distinct Map entries.

Which array method should you apply to run a function for every item within an array returning an array of all items for which the function is true?

forEach(callback) method is an efficient way to iterate over all array items. Its first argument is the callback function, which is invoked for every item in the array with 3 arguments: item, index, and the array itself.

How do you check if every element in an array is the same?

To check if all values in an array are equal:Use the Array. every() method to iterate over the array. Check if each array element is equal to the first one. The every method only returns true if the condition is met for all array elements.


Video Answer


1 Answers

It's an extension of the fact that forEach only visits elements that actually exist. I don't know that there's a deeper "why" for that other than that it didn't make much sense to call the callback for a missing element.

You can realize those elements (if that's the world) by using:

  1. Spread notation, or
  2. Array.from, or
  3. Array.prototype.values, or
  4. Array.prototype.entries

...or possibly some others.

const a = [, , 3];
console.log(a.hasOwnProperty(0)); // false
const b = [...a];
console.log(b.hasOwnProperty(0)); // true
const c = Array.from(a);
console.log(b.hasOwnProperty(0)); // true

Applying that to your function with Array.from:

const arr1 = [, , 3, 4]
const arr2 = [1, 2, 3, 4]
const result = Array.from(arr1).every((item, index) => item === arr2[index])
console.log(result) // false

Of course, that involves creating a new array and looping through the previous one copying over the elements. You might be better off with your own for loop.

Applying Array.prototype.entries to your function:

const arr1 = [, , 3, 4]
const arr2 = [1, 2, 3, 4]
let result = true;
for (const [index, value] of arr1.entries()) {
    if (value !== arr2[index]) {
        result = false;
        break;
    }
}
console.log(result) // false
like image 196
T.J. Crowder Avatar answered Sep 20 '22 12:09

T.J. Crowder