Reputation: 126125
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')
.
Upvotes: 7
Views: 1512
Reputation: 95242
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.
Upvotes: 4
Reputation: 816364
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
:
this
this
or That?Upvotes: 8