1

I have a user that is generating Sentry reports from this code saying Cannot read property 'values' of undefined

var self = this;
if (self.queue()) {
    return self.queue().some(function (item, index) {
        return item.values[key] == value;
    });
} else {
    return false;
}

self.queue() is a knockout observable. How is this possible? Does array.some loop through empty arrays? Or is there some weirdness with observables that the some function is attached to the real array, and the array is being edited while it's being looped through?

The obvious answer is to do this

var self = this;
if (self.queue()) {
    return self.queue().some(function (item, index) {
        if (item && item.values) {
            return item.values[key] == value;
        }else{
            return false;
        }
    });
} else {
    return false;
}

But I can't see a reason why I should have to do that.

Am I using the some function wrong? Do I need to duplicate the array first before I loop through it?

Thanks

-Edit

This test in node as per GMaiolo's example and Alexey Lebedev's comment

// let arr = [null, undefined, 0, 'something', undefined, 3]
let arr = [null, , , 'something', , 3]
console.log("test 1:");
for (const value of arr) {
    console.log(value)
}
console.log("\ntest 2:");
arr.forEach(function(item){
    console.log(item);
});
console.log("\ntest 3:");
arr.some(function(item){
    console.log(item);
    return false;
});

Results

test 1:
null
undefined
undefined
something
undefined
3

test 2:
null
something
3

test 3:
null
something
3

Tested in node 8.11

2
  • 1
    It's also possible that the array contains things you dont think it does. if (item) { isn't going to stop your error. If item doesn't have a values property, or is null, same error Commented Jun 12, 2018 at 16:07
  • Good point, if one can happen, the other can too, I will edit Commented Jun 12, 2018 at 16:27

1 Answer 1

3

An undefined or null value it's still an array's element in its position, so, answering the particular question:

Yes, Array.some will loop over arrays filled with undefined elements.


That being said, we can test out what I've just said using Array.values:

let arr = [null, undefined, 0, 'something', undefined, 3]
const iterator = arr.values()

for (const value of iterator) {
  console.log(value) // output: null, undefined, 0, "something", undefined, 3
}
Sign up to request clarification or add additional context in comments.

4 Comments

Well that's a game changer... the app has loops everywhere. Thanks for the help.
but not on sparse elements.
What Nina said, [1,,,2].some(x => console.log(x)) will not iterate over undefined's in the middle.
@AlexeyLebedev That doesn't appear to be entirely true for the example in the answer. A for (const value of arr) { will loop through them, but a arr.forEach(function(item){ and arr.some(function(item){ will not. I added my test code to my question. It's not directly relevant because the app uses forEach everywhere (es5 support) but it is interesting how the loops function differently.

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.