gpt4 book ai didi

JavaScript:将内置对象的方法作为回调函数传递

转载 作者:行者123 更新时间:2023-11-30 16:18:10 25 4
gpt4 key购买 nike

我一直在研究 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 不是一个函数,它会抛出。在 Firefox 上我得到这个错误:

TypeError: Function.prototype.call called on incompatible undefined

相反,您可以尝试其中一种回调

Function.call.bind([].concat);
[].concat.bind([]);

但是,问题是这不会正常工作,因为回调是用 4 个参数调用的,而不是 2 个:

  • 上一个值
  • 当前值
  • 当前索引
  • 数组

你想摆脱最后两个,所以你无论如何都需要一个自定义函数。

但是,这些都不是好的方法。每次调用 concat 时,它都会创建一个新数组。因此,如果您想展平一个数组,您应该只调用一次 concat 而不是对数组中的每个项目调用一次:

[].concat.apply([], arrays); // this works

关于JavaScript:将内置对象的方法作为回调函数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35164794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com