I would expect [1].some([1].includes)
to return true, instead I get an error saying:
Uncaught TypeError: Cannot convert undefined or null to object.
Any ideas what would cause this? As I understand, Array.some
accepts a function invoked per array item, which [1].includes
should fulfill.
You lose the context when you pass that function as is: when it's invoked as a callback, value of this
inside it is undefined
in strict mode (and global object in non-strict mode), not [1]
. To address this issue, you may fix the context:
[1].some([].includes.bind([1]))
Note that it doesn't matter which array is used to access includes
function; you might as well write that as...
[1].some( Array.prototype.includes.bind([1]) )
That's be a bit less concise, but a bit more efficient (as no immediate array is created). Still, it almost never should be a bottleneck; thus you should better optimize for readability.
Unfortunately, this won't be enough. See, Array.includes() uses two parameters:
arr.includes(searchElement[, fromIndex])
... and Array.some() does supply it with those two (even three in fact, but only two are used by includes
). That's why this...
[1,2,3].some([].includes.bind([1])); // true
... works, but this...
[2,1,3].some([].includes.bind([1])); // false
... doesn't: the lookups in [1]
array start from 0th, 1st, 2nd elements - and apparently fail after the first one.
To fix this, you might either create a function that takes exactly one argument with something like lodash's _.unary:
[2,1,3].some(_.unary([].includes.bind([1]))) // now we're talking!
... or bite the bullet and use arrow function instead. Note that you can still use a function with a bound context here:
const checker = [].includes.bind([1]);
[2,1,3].some(el => checker(el));
... to make this more flexible.