Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't use String.prototype.match as function for Array.some?

This doesn't work:

var s = '^foo';
console.log(['boot', 'foot'].some(s.match));

Uncaught TypeError: String.prototype.match called on null or undefined

But this does:

var s = '^foo';
console.log(['boot', 'foot'].some(function(i) { return i.match(s) }));

Why is this? I imagine somehow the String.prototype.match function is too "primitive" or something, but why exactly? Since I'm not using ES2015, the second version seems quite verbose. Is there an alternative?

EDIT

When I wrote the above, I actually got it backwards compared to my actual need, which was matching one string against a number of regexes. But thanks to the great answers and comments below, I get it: [/^foo/, /^boo/].some(''.match, 'boot').

like image 811
Steve Bennett Avatar asked Nov 10 '15 05:11

Steve Bennett


People also ask

How do you find the matching string in an array?

indexOf is used for finding substrings inside a given string. If there's no match, it returns -1 , otherwise it returns the starting index of the first match. If that index is 0 , it means the match was in the beginning. will match all strings that begin with "he" , such as "hello", "hear", "helium", etc.

What does match() return in JavaScript?

The match() method returns an array with the matches. The match() method returns null if no match is found.

What is array prototype in JavaScript?

Definition and Usage prototype allows you to add new properties and methods to arrays. prototype is a property available with all JavaScript objects.

What is string prototype in JavaScript?

Definition and Usage The prototype is a property available with all JavaScript objects. The prototype property allows you to add new properties and methods to strings.


2 Answers

Note: The value of this is determined by how the function is called! (exception: bound and arrow functions)

If you pass s.match to .some, then the function will be called with this set to the global object (e.g. window) not the string it "belongs" to.

I.e. it would be equivalent to this:

String.prototype.match.call(window, 'foo')

This cannot work because this has to refer to a string object.

You could solve this by binding the function to a specific this value:

['boot', 'foot'].some(s.match.bind(s));

Learn more about this:

  • MDN - this
  • You Don't Know JS: this or That?
  • How to access the correct `this` context inside a callback?
like image 116
Felix Kling Avatar answered Sep 21 '22 01:09

Felix Kling


A function value in Javascript does not bring its object along with it. The value of s.match is a plain function value, with no knowledge that you happened to find it attached to s. In fact, no matter what String you access it through, it's always the same function value:

"foo".match === "bar".match 
//= true

When you call a function through an object, Javascript sets this to that object for the duration of the function call. But as soon as anything comes between retrieving the function value and calling it, any object association is lost.

You can create a function that does remember a specific this value using bind, as in @Felix King's answer. someFunction.bind(someObject) has approximately the same meaning as function(arg1, arg2,...) { return someObject.someFunction(arg1, arg2,...); }, but it automatically handles the number of parameters properly.

like image 33
Mark Reed Avatar answered Sep 19 '22 01:09

Mark Reed