2017-06-12 49 views
4

所以我想要的數組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 ... 

回答

5

有兩個原因,你不能只是做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

3

這裏是你如何可以實現的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

是的,如果你更喜歡使用效用函數的話,這是一個很好的選擇。 –