`String.prototype.contains(regex)`

# Mathias Bynens (11 years ago)

Both String.prototype.startsWith and String.prototype.endsWith throw a TypeError if the first argument is a RegExp:

Throwing an exception if the first argument is a RegExp is specified in order to allow future editions to define extends that allow such argument values.

However, this is not the case for String.prototype.contains, even though it’s a very similar method. As per the latest ES6 draft, String.prototype.contains(regex) behaves like String.prototype.contains(String(regex)). This seems inconsistent. What’s the reason for this inconsistency?

# Jussi Kalliokoski (11 years ago)

Not sure why the inconsistency, but afaik with for example WebIDL if you say something accepts a string, it accepts pretty much anything that can be coerced to a string, so the case of contains may come from there.

# Benjamin (Inglor) Gruenbaum (11 years ago)

May I ask what String.prototype.contains accomplish with a regular expression (that we don't already have with RegExp.test)?

I keep writing .indexOf(..) !== -1) or shimming contains because that's a problem and contains solves it. I risk being very short sighted here but how could you possible extend contains for anything but a string?

I think that there is no reason to throw rather than allow things that behave like a string in if we don't see any potential for extension.

# Andrea Giammarchi (11 years ago)

+1 to what Benjamin says

# Jason Orendorff (11 years ago)

On Wed, Dec 18, 2013 at 11:16 AM, Benjamin (Inglor) Gruenbaum <inglor at gmail.com> wrote:

May I ask what String.prototype.contains accomplish with a regular expression (that we don't already have with RegExp.test)?

Consistency with the other methods, maybe? It would be bad API design to insist on "there's only one way to do it" at the expense of consistency and the principle of least astonishment.

# Andrea Giammarchi (11 years ago)

then none of them should throw, imho

startsWith is like dropping the /^ form a RegExp, endsWith like dropping the $/ part .. that's it

The problem with RegExp is usually the safe escaping, having 1 char less to type for a .test() - so actually counting chars in the method name is even more - is not a win

In /^th(is|at)$/.test(str) the useful RegExp part is in the middle so what was the reason to not coerce to string as basically every other String.prototype method does already if consistency was actually the reason ?

Is it because split accepts RegExp too ? 'cause that's completely different scenario.

# Benjamin (Inglor) Gruenbaum (11 years ago)

I agree both with what Jason said and what Andrea said,

It needs to be consistent and I think the way Andrea suggests is the correct one.

If anything, I'd expect all of them to throw when passed multiple arguments for forward compatibility. It might be useful to check multiple values in contains/endsWith/startsWith or constrain it in some way.

# Mathias Bynens (11 years ago)

On 18 Dec 2013, at 23:02, Benjamin (Inglor) Gruenbaum <inglor at gmail.com> wrote:

If anything, I'd expect all of them to throw when passed multiple arguments for forward compatibility. It might be useful to check multiple values in contains/endsWith/startsWith or constrain it in some way.

The reason String.prototype.{starts,ends}With throw when passed a regular expression is forward compatibility:

Note 2. Throwing an exception if the first argument is a RegExp is specified in order to allow future editions to define extends that allow such argument values.

It seems that contains was forgotten about when ecmascript#498#c3 was fixed, so I’ve filed ecmascript#2407 asking to make String.prototype.contains(regex) throw as well.

# Brendan Eich (11 years ago)

Thanks!