55

Why does the "in" operator in Javascript return true when testing if "0" exists in array, even when the array doesn't appear to contain "0"?

For example, this returns true, and makes sense:

var x = [1,2];
1 in x; // true

This returns false, and makes sense:

var x = [1,2];
3 in x; // false

However this returns true, and I don't understand why:

var x = [1,2];
0 in x;
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Mariano Peterson
  • 774
  • 1
  • 6
  • 7

6 Answers6

86

It refers to the index or key, not the value. 0 and 1 are the valid indices for that array. There are also valid keys, including "length" and "toString". Try 2 in x. That will be false (since JavaScript arrays are 0-indexed).

See the MDN documentation.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
22

The in operator doesn't do what you're thinking it does. The in operator returns true if the specified operand is a property of the object. For arrays, it returns true if the operand is a valid index (which makes sense if think of arrays as a special-case object where the properties are simply named 0, 1, 2, ...)

For example, try this:

var x=[1,4,6];
alert(2 in x);

It'll also return true, because "2" is a valid index into the array. In the same way, "0" is an index into the array, so also returns true.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Dean Harding
  • 71,468
  • 13
  • 145
  • 180
  • 1
    *"(which makes sense if think of arrays as a special-case object where the properties are simply named 0, 1, 2, ..."* Which is what they are, per the spec. JavaScript engines optimize them when possible of course. :-) – T.J. Crowder Apr 30 '21 at 12:31
13

I guess you use Python before, in JS, use Array.prototype.includes

let x = [1, 2]
x.includes(1) // true

in operator check the indices of the array not the value

0 in [1, 2] // true
2 in [1, 2] // false
Brady Huang
  • 1,852
  • 20
  • 23
9

Javascript's in operator does not check if a value is contained in an array. It checks if the object has a property or index. So var x = [4,5]; 4 in x; //false 1 in x; //true.

Because length is a property of x, "length" in x; //true

Sean
  • 4,450
  • 25
  • 22
8

Modern browsers, except IE, support a couple methods that can find a value in an array.

indexOf and lastIndexOf return the first(or last) index of an exact match of their argument in an array, or -1, if no matching element was found.

if(A.indexOf(0)!= -1){
    // the array contains an element with the value 0.
}

You can add one or both methods to IE and older browsers-

if(![].indexOf){
    Array.prototype.indexOf= function(what, i){
        i= i || 0;
        var L= this.length;
        while(i< L){
            if(this[i]=== what) return i;
            ++i;
        }
        return -1;
    }
    Array.prototype.lastIndexOf= function(what, i){
        var L= this.length;
        i= i || L-1;
        if(isNaN(i) || i>= L) i= L-1;
        else if(i< 0) i += L;
        while(i> -1){
            if(this[i]=== what) return i;
            --i;
        }
        return -1;
    }
}
kennebec
  • 102,654
  • 32
  • 106
  • 127
  • Thank you providing a workaround to the problem rather than just an explanation as to why it doesn't work. – Bobort Jan 23 '17 at 20:27
3

just like the js for in loop which iterates the object properties, the in operator checks if the specified property is in the specified object or its prototype chain. it does not check whether an element is in an array.

let's say x is an array, use x.includes(element) to return true/false in nodejs/modern-browsers. As for loop, use for(let element of x) since x is a js iterable.

LeOn - Han Li
  • 9,388
  • 1
  • 65
  • 59