0

Apparently 0 in [3,1] is not the right way to find out whether a set contains an item. Is there a JS compatible way to do this without iterating the collection?

Peter Wone
  • 15,594
  • 12
  • 74
  • 106
  • Now it's a duplicate of [array.contains(obj) in JavaScript](http://stackoverflow.com/q/237104/218196) – Felix Kling Apr 11 '14 at 03:14
  • And that's no problem at all because chances someone will find what they seek is now higher. I can never see what's wrong with supporting multiple search vectors. It's not *my* fault JS `in` has different semantics from every other language in software history. :) – Peter Wone Apr 11 '14 at 03:27

1 Answers1

2

You'd think 0 in [3,1] would evaluate to false. But it evaluates to true. I think this is because null, false and zero are sometimes treated as equivalent.

No, you have a misunderstanding of what in does. It tests whether the object has a property with that name. Arrays are just objects with numeric properties:

> console.dir([3,1]);
  Array[2]
    0: 3
    1: 1
    length: 2

The array has an element at index 0, hence the test is true. 'length' in [3,1] returns true as well.

null, false and zero are sometimes treated as equivalent

null, false and 0 are all "falsy" values, i.e. they become to false when converted to a Boolean. This is consistent with other dynamically typed languages, such as PHP or Python.

JavaScript can have surprising behavior, especially when it comes to type conversion, but it is deterministic. It's recommended to simply avoid type conversion if possible.

Felix Kling
  • 705,106
  • 160
  • 1,004
  • 1,072
  • OK, great at least now it doesn't seem completely crazy. Is there a simple way to do what I thought I was doing, ie find out whether an array contains a specific value? First thought: a.indexOf(item) != -1 (but I don't know whether this is legal in JS) – Peter Wone Apr 11 '14 at 03:11
  • Yep, `indexOf` would be the way to go, if you don't have to support older IE versions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Browser_compatibility. Otherwise you have to iterate over the array explicitly. – Felix Kling Apr 11 '14 at 03:12
  • Older than what? The oldest I support is IE8. Asking programmers to support IE7 would cause a general strike :) Oh drat your reference say IE9+ – Peter Wone Apr 11 '14 at 03:15
  • `indexOf` was added in IE9 :-/ However, there is a polyfill provided in the MDN documentation. Since you completely changed your question though, my answer doesn't make sense anymore. You should know better than doing that. – Felix Kling Apr 11 '14 at 03:15
  • OK today I learnt *two* things. A polyfill is a standard hack for backward compatibility, and `in` is a *faux ami*. While I was bundling the polyfill I threw in contains just for some syntactic candy. So now I can have `[3,1].contains(0)` returning false, hurrah hurrah all is well in the world. – Peter Wone Apr 11 '14 at 03:23