admin管理员组

文章数量:1202350

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????)

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?

Share Improve this question edited Aug 7, 2019 at 12:47 T.J. Crowder 1.1m199 gold badges2k silver badges1.9k bronze badges asked Aug 7, 2019 at 12:37 Joe LloydJoe Lloyd 22.3k7 gold badges58 silver badges82 bronze badges 1
  • "callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values." Right there in the documentation on MDN. – epascarello Commented Aug 7, 2019 at 13:00
Add a comment  | 

4 Answers 4

Reset to default 14

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

Because the language design says so.

本文标签: