I'm getting a strange error when trying to pass Array.from
to Array.prototype.map
.
let fn = Array.from.bind(Array); // [Function: bound from]
fn('test') // [ 't', 'e', 's', 't' ]
['test'].map(s => fn(s)) // [ [ 't', 'e', 's', 't' ] ]
['test'].map(fn) // TypeError: 0 is not a function
Full Error:
TypeError: 0 is not a function
at Function.from (native)
at Array.map (native)
at repl:1:10
at REPLServer.defaultEval (repl.js:260:27)
at bound (domain.js:287:14)
at REPLServer.runBound [as eval] (domain.js:300:12)
at REPLServer.<anonymous> (repl.js:429:12)
at emitOne (events.js:95:20)
at REPLServer.emit (events.js:182:7)
at REPLServer.Interface._onLine (readline.js:211:10)
What's going on?
map
calls its callback with three arguments: The entry, the index, and the object being iterated over. Array.from
expects that if a second argument is given to it, it's a mapping function, and so tries to call it on each "element" it's building the array out of. The index, 0
on the first call, isn't a function, so Array.from
fails.
Put it another way, the equivalent of
['test'].map(fn)
is not
['test'].map(e => fn(e))
but rather
['test'].map((e, i, a) => fn(e, i, a))
...where e
is the entry, i
is its index, and a
is the "array" being traversed by map
. Since i
is not a function, Array.from
fails.
You get the same sort of thing with several other array functions, such as forEach
, some
, ...
If you do this a lot, you may find it useful to have a function you can use to filter all but the first argument:
function passOneArg(f) {
return function(a) { return f.call(this, a); };
}
which you can use like this:
['test'].map(passOneArg(fn))
Or possibly even
function limitArgs(f, count) {
return function() {
return f.apply(this, Array.prototype.slice.call(arguments, 0, count));
};
}
then
['test'].map(limitArgs(fn, 1))
Those are, of course, two of the worst function names on the planet, but you get the idea... :-)
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