Javascript:回调中的无点风格

问题描述:

所以我想要的数组arr1的元素也碰巧属于数组arr2。我想arr1.filter(arr2.includes)应该做的伎俩,但它给了我一个错误(见下文)。奇怪的是,arr1.filter(x => arr2.incudes(x))工作正常。即使函数arr2.includesx => arr2.includes(x)不是平等的,它们不应该在相同的输入上采用相同的值吗?我在想什么,在这里?Javascript:回调中的无点风格

> 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将索引传递给索引时,它将使用该索引并跳过前导条目。

所以,通常的解决办法是使用知道它需要使用上arr2includes,知道只有通过它的包装功能的一个参数  —这是你与你的箭头功能做了什么。

但是也可以参考Michał Perłakowski's answer以获得函数式编程观点的答案,使用效用函数创建回调函数而不是创建内联函数。

+0

值得注意的是通过查找'Array.prototype.includes'是相当缓慢的。对于像两个数组''Set'的交集这样的设置操作应该被使用。 – ftor

这里是你如何可以实现的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>

+0

是的,如果你更喜欢使用效用函数的话,这是一个很好的选择。 –