0

Given a variable str containing a string value, are these two lines of code equivalent?

Line A:

if ( [ 'foo', 'bar', 'baz' ].indexOf( str ) > -1 ) {

Line B:

if ( /^foo|bar|baz$/.test( str ) ) {
Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • possible duplicate of [Is there a version of JavaScript's String.indexOf() that allows for regular expressions?](http://stackoverflow.com/questions/273789/is-there-a-version-of-javascripts-string-indexof-that-allows-for-regular-expr) – Daniel A. White Nov 27 '11 at 03:09
  • 2
    Not quite a duplicate. He wants to convert indexOf to a regex, that question wants to call indexOf on a regex. – Dan Nov 27 '11 at 03:11

3 Answers3

2

Not quite. The pipes are including the ^ and $ as alternatives. I'm not entirely clear on the syntax of JS's regular expressions, but if you're looking for str to contain only foo, or bar, or baz, use the expression /^(foo|bar|baz)$/. If you're looking to do something different, let me know and I'll try to clear it up.

Dan
  • 10,531
  • 2
  • 36
  • 55
  • I would like to achieve the behavior of Line A with Line B. (So, yes, I want to check if `str` is exactly one of those 3 values... ) – Šime Vidas Nov 27 '11 at 03:09
  • 1
    Then yes, you want the regex I gave you. Alternately, if you don't need to capture /which/ value you match, you can use `/^(?:foo|bar|baz)$/`. The `?:` means 'don't bother remembering which one of these three matches', and it might be a bit faster – Dan Nov 27 '11 at 03:10
  • Could you explain why i have to group my `a|b|c`? How does it make a difference? – Šime Vidas Nov 27 '11 at 03:19
1

Okay, after the edit, they're still not equivalent since test will call toString. See:

var myItem = {toString: function() { return 'foo'; }};

['foo', 'bar', 'baz'].indexOf(myItem); // -1
/^(foo|bar|baz)$/.test(myItem); // true

http://jsfiddle.net/hqu7D/

Even when they're string values (sorry, missed that) then they're still not equivalent because there are two different types of strings and indexOf uses strict equality/identity:

http://jsfiddle.net/HpCUY/

To make them truly equivalent, you can either call .toString() before using indexOf, or you can test Object.prototype.toString.call(myItem) === '[object String]' before using test.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Still they're different. Minitech gave you a few examples of things that B will catch that A will not, and see the regex I gave you for how to fix it. – Dan Nov 27 '11 at 03:09
  • @minitech Yes, but I mentioned in my question that `str` is a string value... It can't be an object. – Šime Vidas Nov 27 '11 at 03:16
  • @ŠimeVidas: Sorry, missed that. I edited my answer again - they're [still not equivalent](http://jsfiddle.net/HpCUY/). – Ry- Nov 27 '11 at 03:20
  • @minitech Uh... `:)` When I said "string value", I meant a value of the String type, not a String object... (String objects are useless, I would never use them... ) – Šime Vidas Nov 27 '11 at 03:22
  • @ŠimeVidas: I know :) But your question is tagged [tag:theory], and this is a possibility. jQuery does it too. – Ry- Nov 27 '11 at 03:25
  • @minitech I guess "string value" is kind-of ambiguous - I should have said "value of type String". jQuery does what? Uses `new String()`? – Šime Vidas Nov 27 '11 at 03:28
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/5384/discussion-between-minitech-and-sime-vidas) – Ry- Nov 27 '11 at 03:30
1

No, they are not.

The method indexOf() returns -1 if the item is not found in the array, or the position of the array if it is found in the array.

The method test returns true if the regex finds a match, and false if it doesn't.

If your regular expression was instead /^(foo|bar|baz)$/, then the function would be the same.

Nightfirecat
  • 11,432
  • 6
  • 35
  • 51