Array.prototype.includes et Array.prototype.indexOf

112

Au-delà de la lisibilité améliorée, y a-t-il un avantage à includessur indexOf? Ils me semblent identiques.

Quelle est la différence entre ceci

var x = [1,2,3].indexOf(1) > -1; //true

Et ça?

var y = [1,2,3].includes(1); //true
Mat
la source
12
includesa un support de navigateur bien pire.
Quentin
4
Notez que cela includesne fait pas partie de ES6 / ES2015. Il s'agit d'une proposition pour la prochaine version d'ECMAScript et sera ajoutée cette année.
Felix Kling
4
includes
Je

Réponses:

138

tl; dr: NaN est traité différemment:

  • [NaN].indexOf(NaN) > -1 est false
  • [NaN].includes(NaN) est true

De la proposition :

Motivation

Lors de l'utilisation de tableaux ECMAScript, il est généralement souhaitable de déterminer si le tableau comprend un élément. Le schéma dominant pour cela est

if (arr.indexOf(el) !== -1) {
    ...
}

avec diverses autres possibilités, par exemple arr.indexOf(el) >= 0, ou même ~arr.indexOf(el).

Ces modèles présentent deux problèmes:

  • Ils ne parviennent pas à "dire ce que vous voulez dire": au lieu de demander si le tableau comprend un élément, vous demandez quel est l'indice de la première occurrence de cet élément dans le tableau, puis comparez-le ou tournez-le, pour déterminer la réponse à votre question réelle.
  • Ils échouent NaN, comme indexOfutilise la comparaison stricte d'égalité et donc [NaN].indexOf(NaN) === -1.

Solution proposée

Nous proposons l'ajout d'une Array.prototype.includesméthode, de sorte que les motifs ci-dessus puissent être réécrits comme

if (arr.includes(el)) {
    ...
}

Cela a presque la même sémantique que ci-dessus, sauf qu'il utilise l'algorithme de comparaison SameValueZero au lieu de Strict Equality Comparison, ce qui rend [NaN].includes(NaN)vrai.

Ainsi, cette proposition résout les deux problèmes rencontrés dans le code existant.

Nous ajoutons en outre un fromIndexparamètre, similaire à Array.prototype.indexOfet String.prototype.includes, par souci de cohérence.


Informations complémentaires:

Félix Kling
la source
1
Seulement la moitié de la vérité. Différent également: les éléments manquants sont traités comme undefinedpar .includes()et ne sont pas considérés par .indexOf().
Robert Siemer
11

Si vous vous interrogez sur les performances, pour le moment, indexOf est plus rapide, mais ce test JSperf a tendance à montrer que plus le temps passe, plus includes()sera plus rapide queindexOf (je suppose que ce sera encore optimisé).

IMHO, je préfère aussi écrire if (arr.includes(el)) {}car il est plus clair et plus maintenable queif (arr.indexOf(el) !== -1) {}

538ROMEO
la source
1
On dirait que la différence de performance n'est pas si évidente. Mon mobile Firefox montre que indexOf est en fait plus rapide. Certaines versions de Chrome agissent de la même manière ... Mais la différence semble de toute façon négligeable dans les implémentations d'aujourd'hui.
Nux
8

.indexOf() et .includes() méthodes peuvent être utilisées pour rechercher un élément dans un tableau ou pour rechercher un caractère / sous-chaîne dans une chaîne donnée.

Utilisation dans la baie

( Lien vers la spécification ECMAScript)

  1. indexOfutilise la comparaison d'égalité stricte alors que includesl' algorithme SameValueZero est utilisé . Pour cette raison, les deux points de divergence suivants se posent.

  2. Comme l'a souligné Felix Kling , le comportement est différent en cas de NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. Le comportement est également différent en cas de undefined.
let arr = [ , , ];

arr.indexOf(undefined); // returns -1; meaning undefined is not present
arr.includes(undefined); // returns true

Utilisation en chaîne

( Lien vers la spécification ECMAScript)

  1. Si vous passez un RegExp à indexOf, il traitera le RegExp comme une chaîne et renverra l'index de la chaîne, s'il est trouvé. Cependant, si vous passez un RegExp à includes, il lèvera une exception.
let str = "javascript";

str.indexOf(/\w/); // returns -1 even though the elements match the regex because /\w/ is treated as string
str.includes(/\w/); // throws TypeError: First argument to String.prototype.includes must not be a regular expression

Performance

Comme l'a souligné 538ROMEO , includespeut être un peu (très petit) peu plus lent (car il doit rechercher une expression régulière comme premier argument) queindexOf mais en réalité, cela ne fait pas beaucoup de différence et est négligeable.

L'histoire

String.prototype.includes()a été introduit dans ECMAScript 2015 alors qu'il a Array.prototype.includes()été introduit dans ECMAScript 2016. En ce qui concerne la prise en charge du navigateur, utilisez-les à bon escient.

String.prototype.indexOf()et Array.prototype.indexOf()sont présents dans l'édition ES5 d'ECMAScript et donc pris en charge par tous les navigateurs.

Srishti
la source
indexOfdonne trueaprès mise explicitement undefineddans un tableau:let arr=[undefined]; ou let arr=[];arr[0]=undefined;maintenantarr.indexOf(undefined) === 0
Jay Dadhania
Vous êtes le seul à indiquer la différence avec undefined: La raison en est que .includesles éléments manquants sont traités comme undefined, tandis que.indexOf() ignorant. Vous pouvez également «créer» des éléments manquants avec arr[number beyond length] = whatever.
Robert Siemer
Personne ne demandait de chaînes, mais vos remarques suggèrent que .includes()ne mange que des chaînes. En réalité, les deux méthodes contraignent n'importe quoi à une chaîne aussi bonne que possible. Regex est expressément exclu comme argument pour .includes()pour permettre des ajouts futurs à la norme selon le projet actuel.
Robert Siemer
4

Conceptuellement, vous devriez utiliser indexOf lorsque vous voulez utiliser la position indexOf qui vous donne simplement pour extraire la valeur ou opérer sur le tableau, c'est-à-dire en utilisant slice, shift ou split après avoir obtenu la position de l'élément. D'autre part, Use Array.includes uniquement pour savoir si la valeur est à l'intérieur du tableau et non la position car vous ne vous en souciez pas.

Sébastien Gomez
la source
0

indexOf() et includes() peuvent tous deux être utilisés pour rechercher des éléments dans un tableau, cependant chaque fonction produit des valeurs de retour différentes.

indexOf renvoie un nombre (-1 si l'élément n'est pas présent dans le tableau, ou la position du tableau si l'élément est présent).

includes()renvoie une valeur booléenne ( trueou false).

Kruti
la source
Salut Kruti, cette question a déjà reçu une réponse et elle a une réponse acceptée. De plus, vous pouvez voir comment votre réponse ne contient que des informations déjà mentionnées dans d'autres réponses. La question, au final, a déjà 4 ans. Veuillez fournir des conseils sur les questions les plus récentes ou celles sans réponse. Merci
leonardfactory