Javascript: 回调中的无点样式

Javascript: point-free style in callback

所以我想要数组 arr1 中恰好也属于数组 arr2 的元素。我认为 arr1.filter(arr2.includes) 应该可以解决问题,但它给了我一个错误(见下文)。但奇怪的是,arr1.filter(x => arr2.incudes(x)) 工作正常。即使函数 arr2.includesx => arr2.includes(x) 在引用上不相等,它们不应该在相同的输入上采用相同的值吗?我在这里错过了什么?

> arr1 = ['a', 'b', 'c']
[ 'a', 'b', 'c' ]
> arr2 = ['a', 'c', 'd']
[ 'a', 'c', 'd' ]
>
> arr1.filter(x => arr2.includes(x))
[ 'a', 'c' ]
> arr1.filter(arr2.includes)
TypeError: Cannot convert undefined or null to object
    at includes (<anonymous>)
    at Array.filter (native)
    at repl:1:6
    ... etc ...

有两个原因你不能只做 arr1.filter(arr2.includes):

  1. arr2.includes 只是对函数的引用,但您需要的是对函数 对数组的引用想在 (arr2) 上使用它。您可以使用 Function.prototype.bind 解决该问题,但是:

  2. filter 向其回调传递多个参数,而不仅仅是一个:它传递值、其索引和原始数组。 includes 将尝试使用它收到的第二个参数作为开始搜索的索引,因此当 filter 将索引传递给它时,它将使用它并跳过前导条目。

所以通常的解决方案是使用一个包装函数,它知道它需要在 arr2 上使用 includes 并且知道只向它传递一个参数——这就是你所做的你的箭头函数。

但另请参阅 从函数式编程的角度使用实用函数创建回调函数而不是内联创建它的答案。

以下是实现可用于无点样式的 includes 函数的方法:

const arr1 = ['a', 'b', 'c'];
const arr2 = ['a', 'c', 'd'];
const includes = arr => x => arr.includes(x);
console.log(arr1.filter(includes(arr2)));

如果您对 JavaScript 中的函数式编程感兴趣,您应该尝试 Ramda 库。使用 Ramda,您的代码可能如下所示:

const arr1 = ['a', 'b', 'c'];
const arr2 = ['a', 'c', 'd'];
// First option: R.flip
console.log(R.filter(R.flip(R.contains)(arr1), arr2));
// Second option: R.__ (placeholder argument)
console.log(R.filter(R.contains(R.__, arr1), arr2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>