简体   繁体   English

在javascript中使用高阶函数中的原型函数

[英]Using prototype functions in higher order functions in javascript

I'm trying to concat an array of arrays using reduce and I figured that I could use the Array.prototype.concat function like this: 我正在尝试使用reduce来连接一个数组数组,我想我可以像这样使用Array.prototype.concat函数:

arr = [[1],[2],[3]]
arr.reduce((a, b) => Array.prototype.concat(a, b), [])

Which works fine and gives me the array [1, 2, 3] . 哪个工作正常,并给我阵列[1, 2, 3] Then I thought I could be even smarter and do it like this: 然后我想我可以变得更聪明,并且这样做:

arr = [[1],[2],[3]]
arr.reduce(Array.prototype.concat, [])

This however gives me an error: 但是这给了我一个错误:

TypeError: Array.prototype.concat called on null or undefined
    at Array.reduce (native)
    at Object.<anonymous> (/home/axel/Developer/temp/reduce2.js:2:5)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.runMain (module.js:590:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)

It seems to think that Array.prototype.concat is undefined . 似乎认为Array.prototype.concat undefined Why is this? 为什么是这样?

concat operates as a method with respect to some object (ie, the this value of the method's execution). concat作为一个关于某个对象的方法(即方法执行的this值)运行。 When you pass a function into a function, you do not pass along any this value. 将函数传递给函数时,不传递任何this值。 Thus, you're effectively doing something similar to: 因此,你有效地做了类似的事情:

var rawConcat = Array.prototype.concat;
rawConcat(a,b);

You can use bind to create a copy of a function with a particular this burned into it: 你可以使用bind来创建一个函数的副本,其中特定的this被烧入其中:

arr.reduce(Array.prototype.concat.bind(Array.prototype), [])

However, now that that's cleared up, there are several other issues that stop you from doing this. 但是,现在已经解决了,还有其他几个问题阻止你这样做。

For one, reduce actually gets four arguments, including the current index and the whole array. 首先, reduce实际上有四个参数,包括当前索引和整个数组。 You ignore these by having your (a,b)=> lambda only pass two of those four arguments into concat . 你通过让你的(a,b)=> lambda只将这四个参数中的两个传递给concat忽略这些。 That's fine, but when you supply a function directly as an argument to reduce , it will use all four arguments, so you'll get the result of the call Array.prototype.concat(a, b, currentIndex, arr) . 这很好,但是当你直接提供一个函数作为reduce的参数时,它将使用所有四个参数,因此你将获得调用Array.prototype.concat(a, b, currentIndex, arr)

Furthermore, what you're doing isn't a sensible use of Array.prototype . 此外,您正在做的不是合理使用Array.prototype The concat function concatenates its arguments and appends them to a copy of the this value. concat函数连接其参数并将它们附加this值的副本。 Since Array.prototype is itself just an empty array (albeit with many own-properties that other arrays use as inherited properties), this is effectively the same as [].concat(a,b) or (perhaps even more readably) a.concat(b) . 由于Array.prototype本身只是一个空数组(尽管有许多其他数组用作继承属性的自有属性),这实际上与[].concat(a,b)或(甚至更可读) a.concat(b)

Array.prototype.concat expects the context ( this ) to be an Array and in your first example the context is actually Array.prototype which incidentally looks exactly like an Array, hence it works. Array.prototype.concat期望上下文( this )是一个数组,在你的第一个例子中,上下文实际上是Array.prototype ,它偶然看起来像一个数组,因此它可以工作。

Your second example however, passes the concat function by reference so the context is null or undefined. 但是,您的第二个示例通过引用传递concat函数,因此上下文为null或未定义。

The more correct way to do this would be to use Function.prototype.call to bind the context to one of the arrays or call the method directly on the array, eg 更正确的方法是使用Function.prototype.call将上下文绑定到其中一个数组或直接在数组上调用方法,例如

arr = [[1],[2],[3]];
arr.reduce((a, b) => Array.prototype.concat.call(a, b), []);

// Or

arr.reduce((a, b) => a.concat(b), []);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM