I ran into a weird thing while trying to use String methods with higher-order functions. This will throw an error:
['a', 'b'].some('boo'.includes)
I have to wrap the predicate in another function to make it work. But isn't 'boo'.includes
already a function?
This works with plain functions:
const boo = {
includes: () => true
};
['a', 'b'].some(boo.includes)
Is there some special property of String methods that prevents them from being composed like this?
"boo".includes
is nothing else than String.prototype.includes
. Calling it on the string "boo" however sets this
to "boo", which gives the proper context to the function. E.g. "boo".includes("b")
is the same as String.prototype.includes.call("boo", "b")
.
Passing it as an argument, e.g. ['a', 'b'].some('boo'.includes)
, is the same as ['a', 'b'].some(String.prototype.includes)
, which then lacks the proper this
as context.
You can of course use e.g. bind
: ['a', 'b'].some(String.prototype.includes.bind("boo"))
, or use the optional second parameter thisArg for some
: ['a', 'b'].some(String.prototype.includes, "boo")
. This will get rid of the error. However, you will then notice, that some
passes not only the element, but the index as second parameter, and the array itself as third. This is a problem, as includes
also takes an optional second parameter for the start position. This causes likely unwanted behavior, as e.g. the array element "b" is at index 1, and "boo".includes("b", 1) === false
.
All in all, you need a function which is so different to String.prototype.includes
, that it's just easier to wrap it in a new function that actually does what you want:
['a', 'b'].some(e => "boo".includes(e))
, as you already noticed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With