JavaScript: passing built-in objects' methods as callback functions -
i've been working through eloquent javascript's exercises , found out think odd. wrote trivial array-flattening piece of code:
var arrays = [[1, 2, 3], [4, 5], [6]]; var out = arrays.reduce(function(acc, next){ return acc.concat(next); }); console.log(out); // → [1, 2, 3, 4, 5, 6]
so far good. didn't seem pretty me, rewrote as:
var arrays = [[1, 2, 3], [4, 5], [6]]; var my_concat = function(acc, next){ return acc.concat(next); } var out = arrays.reduce(my_concat); console.log(out); // → [1, 2, 3, 4, 5, 6]
it better, need introduce function, anonymous or named, such basic thing? array.prototype.concat.call
's call signature need! feeling smart, rewrote code again:
var arrays = [[1, 2, 3], [4, 5], [6]]; var out = arrays.reduce([].concat.call); // → typeerror: arrays.reduce not function (line 2)
well, haven't turned out expected. error message seemed cryptic me.
i decided investigate. works:
var arrays = [[1, 2, 3], [4, 5], [6]]; var my_concat = function(acc, next){ return [].concat.call(acc,next); } var out = arrays.reduce(my_concat); console.log(out); // → [1, 2, 3, 4, 5, 6]
and works:
var arrays = [[1, 2, 3], [4, 5], [6]]; arrays.my_concat = function(acc, next) { return [].concat.call(acc, next); } var out = arrays.reduce(arrays.my_concat); console.log(out); // → [1, 2, 3, 4, 5, 6]
more tinkering in console:
[].concat.call // → call() { [native code] } typeof [].concat.call // → "function" [].concat.call([1, 2, 3], [4, 5]) // → [1, 2, 3, 4, 5] var cc = [].concat.call cc // → call() { [native code] } typeof cc // → "function" cc([1, 2, 3], [4, 5]) // → uncaught typeerror: cc not function(…)
and works:
array.prototype.my_concat = function(acc, next) { return [].concat.call(acc, next); } // → function (acc, next) { return [].concat.call(acc, next); } [[1, 2, 3], [4, 5], [6]].reduce([].my_concat) // → [1, 2, 3, 4, 5, 6] [[1, 2, 3], [4, 5], [6]].reduce([].concat.call) // → uncaught typeerror: [[1,2,3],[4,5],[6]].reduce not function(…)
is there special built-in functions .call
?
call
method functions inherit function.prototype
. is,
arrays.reduce.call === function.prototype.call
the call
method knows function want call because function passed this
value.
when pass call
callback, called passing undefined
this
value. since undefined
not function, throws. on firefox error:
typeerror: function.prototype.call called on incompatible undefined
instead, try 1 of these callbacks
function.call.bind([].concat); [].concat.bind([]);
however, problem won't work properly, because callback called 4 arguments, not 2:
- previousvalue
- currentvalue
- currentindex
- array
you want rid of last two, need custom function anyways.
however, these not approaches. each time call concat
, creates new array. therefore, if want flatten array, should call concat
once instead of per each item in array:
[].concat.apply([], arrays); // works
Comments
Post a Comment