3

I have a piece of code which checks for equality of arrays. It works like a charm when using it like:

[1, 2, 3].equals([1, 2, 3]); // true
[1, 2, 3].equals([1, 2, 4]); // false

The above result is obvious and correct, of course. However, the following case fails:

[1, 2, undefined].equals([1, 2, undefined]);
// Error:  Cannot read property 'equals' of undefined

What could be the cause of it? I check whether it has the property before using it (if (this[i].equals)), so why does it say this? It is also true that undefined === undefined, so I do not see what's the problem.

The function:

Array.prototype.equals = function(arr) {
    if (this.length !== arr.length) {
        return false;
    }

    for (var i = 0; i < arr.length; i++) {
        if (this[i].equals) {
            if (!this[i].equals(arr[i])) {
                return false;
            } else {
                continue;
            }
        }

        if (this[i] !== arr[i]) {
            return false;
        }
    }

    return true;
}
2
  • 1
    @patrickdw beat me to the correct answer, so I'll just add this: a) I suggest that you add if (this==arr) return true; to the top of your test for a fast out when the same object is passed as an argument; b) you should cache the length of your array for speed, for (var i=0,len=arr.length;i<len;++i){ .. } Commented Feb 12, 2011 at 14:18
  • 1
    @Phrogz: I'm not suffering from benchmark problems, but time savings are never bad, thanks. Also thanks for your first suggestion. Commented Feb 12, 2011 at 14:21

1 Answer 1

2

This line:

    if (this[i].equals) {

should be:

    if (this[i] && this[i].equals) {

so that if this[i] is undefined, you won't be trying to access a property on undefined.


EDIT: Since you seem to be testing for an Array, it will be safer to do a more explicit test, since any Object could potentially have an .equals property.

You may want to do this instead:

if( Object.prototype.toString.call( this[i] ) === '[object Array]' ) {

It's a bit longer, but will accurately detect an Array, even if it was created using the new keyword, which would throw off the typeof operator.

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

6 Comments

Yes this is the solution, thanks. Is it unallowed to even check for properties of undefined?
@pimvdb: That is correct. You'll get a TypeError when trying to access a property on undefined.
@pimvdb: By the way, since the point of that if() statement is to only enter if you have an Array, you may want to do a more explicit test. If the item at this[i] happens to be an Object that has an equals property, the test will succeed. I'll update.
I can be rather sure that the Object doesn't have an equals function as I know what libraries I'm using. Thanks for the suggestion though.
@pimvdb: Whatever you prefer, but equals wouldn't need to be prototyped into Object. If Number had an equals property, you'd have the same issue. Or if someone created an object literal or some other instance that has its own equals property. Anyway, just thought I'd mention it. :o)
|

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.