Skip to content
This repository

Make _.include/_.contains work with strings. #667

Closed
wants to merge 2 commits into from

4 participants

Ian Bicking Kit Cambridge John-David Dalton Jeremy Ashkenas
Ian Bicking
ianb commented July 10, 2012

This makes _.include() / _.contains() work with strings in addition to collections.

Note String.contains is a proposed method for Harmony: http://wiki.ecmascript.org/doku.php?id=harmony:string_extras – also it's really just another indexOf check, so it seems to make sense.

String.indexOf is present in Javascript 1.0, so a method identity check seemed unnecessary.

I wasn't sure where a doc change would go.

Ian Bicking
ianb commented July 10, 2012

Also, this allows Javascript to naturally coerce the search item to a string. Arguably that's different than how _.include works with Arrays (since it uses === which does not allow this kind of coercion). This is the simplest implementation, but I'd also be comfortable with a type check on target (returning false if the target is not a string).

Ian Bicking
ianb commented July 10, 2012

I also can't figure out why this works with boxed strings, though it seems to (like new String('test')), since typeof new String('test') == 'object'

Kit Cambridge

I also can't figure out why this works with boxed strings, though it seems to (like new String('test')), since typeof new String('test') == 'object'.

Use _.isString instead of typeof.

John-David Dalton

Strings are array-like so that's why this works in modern browsers on the edge version of Underscore.

_.contains('test', 'e'); // => true
Ian Bicking
ianb commented July 10, 2012

_.contains (in current underscore) didn't seem to work because of the test if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; where nativeIndexOf = ArrayProto.indexOf

Note:

_contains('test', 'es'); // => false
John-David Dalton

Note:
_.contains('test', 'es'); // => false

Yap, that's because being array-like means having a length and index properties like "hi"[1]; // i.
That said I dig me some ES6 sugar :P

Jeremy Ashkenas
Owner

Closing as discussed in #668...

Jeremy Ashkenas jashkenas closed this August 31, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 1 author.

Jul 10, 2012
Ian Bicking Make _.include/_.contains work with strings. This matches the upcomin…
…g String.contains method.
223fb83
Ian Bicking Fix test for strings (to also catch boxed strings). And apparently th…
…e test related to boxed strings was backwards.
5dd91ce
This page is out of date. Refresh to see the latest.
5  test/collections.js
@@ -164,6 +164,11 @@ $(document).ready(function() {
164 164
     ok(!_.include([1,3,9], 2), 'two is not in the array');
165 165
     ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values');
166 166
     ok(_([1,2,3]).include(2), 'OO-style include');
  167
+    ok(_.include('test this out', 'out'), 'include with a string');
  168
+    ok(!_.include('test this out', 'not included'), 'include with a string (false)');
  169
+    ok(_.include('1 2 3 4', 3), 'include with a string and number');
  170
+    ok(_.include(new String('test this'), 'test'), 'works with boxed strings');
  171
+    ok(_('test this out').include('this'), 'OO-style include with a string');
167 172
   });
168 173
 
169 174
   test('collections: invoke', function() {
6  underscore.js
@@ -198,11 +198,13 @@
198 198
   };
199 199
 
200 200
   // Determine if a given value is included in the array or object using `===`.
201  
-  // Aliased as `contains`.
  201
+  // Aliased as `contains`.  Or if `obj` is a string, test if the string contains the
  202
+  // substring.
202 203
   _.include = _.contains = function(obj, target) {
203 204
     var found = false;
204 205
     if (obj == null) return found;
205 206
     if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
  207
+    if (_.isString(obj)) return obj.indexOf(target) != -1;
206 208
     found = any(obj, function(value) {
207 209
       return value === target;
208 210
     });
@@ -832,7 +834,7 @@
832 834
       return toString.call(obj) == '[object ' + name + ']';
833 835
     };
834 836
   });
835  
-  
  837
+
836 838
   // Define a fallback version of the method in browsers (ahem, IE), where
837 839
   // there isn't any inspectable "Arguments" type.
838 840
   if (!_.isArguments(arguments)) {
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.