Javascript:回调中的无点样式

时间:2017-06-12 16:35:39

标签: javascript functional-programming this pointfree

所以我希望数组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 ...

2 个答案:

答案 0 :(得分:5)

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

  1. arr2.includes只是对该函数的引用,但您需要的是对要使用它的数组的函数的引用({ {1}})。您可以使用arr2来解决这个问题,但是:

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

    < / LI>

    所以通常的解决方案是使用一个知道它需要在filter上使用includes的包装函数,并知道只传递一个参数 - 这是你用箭头做的功能

    但请参阅Michał Perłakowski's answer,从函数式编程的角度来看,使用实用函数来创建回调函数而不是内联创建它。

答案 1 :(得分:3)

Here's how you could implement an includes function that could be used in point-free style:

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

If you're interested in functional programming in JavaScript, you should try the Ramda library. With Ramda your code could look like this:

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>