2017-06-12 1 views
4

Je voulais donc les éléments du tableau arr1 qui appartiennent aussi au tableau arr2. J'ai pensé arr1.filter(arr2.includes) devrait faire l'affaire, mais il m'a donné une erreur (voir ci-dessous). Curieusement, cependant, arr1.filter(x => arr2.incudes(x)) a bien fonctionné. Même si les fonctions arr2.includes et x => arr2.includes(x) ne sont pas référentiellement égales, ne devraient-elles pas prendre les mêmes valeurs sur les mêmes entrées? Qu'est-ce que j'oublie ici?Javascript: style sans point de rappel

> 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 ... 

Répondre

5

Il y a deux raisons pour lesquelles vous ne pouvez pas faire arr1.filter(arr2.includes):

  1. arr2.includes est juste une référence à la fonction, mais ce que vous avez besoin est à la fois une référence à la fonction et à le tableau sur lequel vous voulez l'utiliser (arr2). Vous pouvez résoudre cela en utilisant Function.prototype.bind, mais:

  2. filter passe son callback plusieurs arguments, pas seulement un: Il passe la valeur, son index, et le tableau d'origine. includes va essayer d'utiliser le second argument qu'il reçoit comme index pour commencer la recherche, donc quand filter lui passera l'index, il l'utilisera et omettra les entrées principales.

Donc, la solution habituelle est d'utiliser une fonction wrapper qui sait qu'il doit utiliser includes sur arr2 et sait passer seulement il l'un argument   — qui est ce que vous avez fait avec votre fonction de flèche.

Mais voir aussi Michał Perłakowski's answer pour une réponse de la perspective de la programmation fonctionnelle en utilisant une fonction utilitaire pour créer la fonction de rappel plutôt que de la créer en ligne.

+0

Il convient de noter qu'une recherche via 'Array.prototype.includes' est plutôt lent. Pour une opération définie comme l'intersection de deux tableaux 'Set' devrait être utilisé. – ftor

3

Voilà comment vous pouvez mettre en œuvre une fonction includes qui pourrait être utilisé dans le style de point gratuit:

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

Si vous êtes intéressé par la programmation fonctionnelle en JavaScript, vous devriez essayer la Ramda bibliothèque. Avec votre code pourrait Ramda ressembler à ceci:

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

Yup, bonne alternative si vous préférez utiliser une fonction utilitaire pour cela. –