Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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

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

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

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

_.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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 11, 2012
  1. Ian Bicking

    Make _.include/_.contains work with strings. This matches the upcomin…

    ianb authored
    …g String.contains method.
  2. Ian Bicking

    Fix test for strings (to also catch boxed strings). And apparently th…

    ianb authored
    …e test related to boxed strings was backwards.
This page is out of date. Refresh to see the latest.
Showing with 9 additions and 2 deletions.
  1. +5 −0 test/collections.js
  2. +4 −2 underscore.js
5 test/collections.js
View
@@ -164,6 +164,11 @@ $(document).ready(function() {
ok(!_.include([1,3,9], 2), 'two is not in the array');
ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values');
ok(_([1,2,3]).include(2), 'OO-style include');
+ ok(_.include('test this out', 'out'), 'include with a string');
+ ok(!_.include('test this out', 'not included'), 'include with a string (false)');
+ ok(_.include('1 2 3 4', 3), 'include with a string and number');
+ ok(_.include(new String('test this'), 'test'), 'works with boxed strings');
+ ok(_('test this out').include('this'), 'OO-style include with a string');
});
test('collections: invoke', function() {
6 underscore.js
View
@@ -198,11 +198,13 @@
};
// Determine if a given value is included in the array or object using `===`.
- // Aliased as `contains`.
+ // Aliased as `contains`. Or if `obj` is a string, test if the string contains the
+ // substring.
_.include = _.contains = function(obj, target) {
var found = false;
if (obj == null) return found;
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ if (_.isString(obj)) return obj.indexOf(target) != -1;
found = any(obj, function(value) {
return value === target;
});
@@ -832,7 +834,7 @@
return toString.call(obj) == '[object ' + name + ']';
};
});
-
+
// Define a fallback version of the method in browsers (ahem, IE), where
// there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) {
Something went wrong with that request. Please try again.