JavaScript:将内置对象的方法作为回调函数传递
JavaScript: passing built-in objects' methods as callback functions
我一直在研究Eloquent JavaScript的练习,发现了一些我认为很奇怪的东西。我写了一段简单的数组扁平化代码:
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]
目前为止,一切都好。但这对我来说似乎并不漂亮,所以我把它改写为:
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]
它更好,但是我们真的需要引入一个函数,无论是匿名的还是命名的,来做这样一个基本的事情吗? Array.prototype.concat.call
的呼叫签名正是我们所需要的!感觉很聪明,我再次重写了代码:
var arrays = [[1, 2, 3], [4, 5], [6]];
var out = arrays.reduce([].concat.call);
// → TypeError: arrays.reduce is not a function (line 2)
好吧,结果并没有像我预期的那样。错误消息对我来说似乎很神秘。
我决定调查。这有效:
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]
这也适用于:
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]
控制台中的更多修补:
[].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 is not a function(…)
即使这样也有效:
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 is not a function(…)
像.call
这样的内置函数有什么特别之处吗?
call
只是大多数函数从Function.prototype
继承的方法。那是
arrays.reduce.call === Function.prototype.call
call
方法知道要调用哪个函数,因为该函数作为this
值传递。
当您将call
作为回调传递时,它将被称为传递undefined
作为this
值。由于undefined
不是函数,因此它会抛出。在火狐上,我收到此错误:
TypeError: Function.prototype.call called on incompatible undefined
相反,您可以尝试以下回调之一
Function.call.bind([].concat);
[].concat.bind([]);
但是,问题是这无法正常工作,因为回调是使用 4 个参数而不是 2 个参数调用的:
- 上一页价值
- 当前值
- 当前指数
- 数组
你想摆脱最后两个,所以你无论如何都需要一个自定义函数。
但是,这些都不是好方法。每次调用 concat
时,它都会创建一个新数组。因此,如果要平展数组,则应仅调用concat
一次,而不是按数组中的每个项目调用:
[].concat.apply([], arrays); // this works
相关文章:
- JavaScript回调函数
- 如何在回调函数中执行流
- 回调函数中传递参数的困难(Google Map API Markers)
- 如何正确地将参数传递给RequireJS回调函数
- 回调函数在python代码中离线
- 从AJAX回调函数中分离数据
- 赋值后的回调函数
- 如何在javascript回调函数中返回多个变量
- 函数表达式,返回回调函数
- 等待回调函数执行
- JavaScript回调函数和Google Feed API
- 如何从ajax成功回调函数中读取javascript变量
- 正在保存JavaScript内部回调函数中的值
- 有没有什么方法可以停止Jquery中的animate(也可以停止完整的回调函数)
- 如何在javascript中添加带有回调函数的按钮点击事件作为window.conf
- 在Golang回调函数中启用CORS
- 在初始函数完成之前调用回调函数
- jQuery Mobile:如何在$.Mobile.changePage之前运行回调函数
- 即使使用回调函数也无法返回值
- 为什么prototypjs观察到回调函数有绑定