Array.prototype.includes ve Array.prototype.indexOf


113

Geliştirilmiş okunabilirlik ötesinde, herhangi bir avantaj orada includesüzerinde indexOf? Benimle aynı görünüyorlar.

Bunun arasındaki fark nedir

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

Ve bu?

var y = [1,2,3].includes(1); //true

12
includesçok daha kötü tarayıcı desteğine sahip.
Quentin

4
Bunun includesES6 / ES2015'in bir parçası olmadığını unutmayın. ECMAScript’in bir sonraki sürümü için bir tekliftir ve bu yıl eklenecektir.
Felix Kling

4
includesIE'de hiç desteklenmediğini de belirtmek istedim
ZvKa

Yanıtlar:


138

tl; dr: NaN farklı şekilde ele alınır:

  • [NaN].indexOf(NaN) > -1 dır-dir false
  • [NaN].includes(NaN) dır-dir true

Gönderen önerisi :

Motivasyon

ECMAScript dizilerini kullanırken, genellikle dizinin bir öğe içerip içermediğini belirlemek istenir. Bunun için geçerli model şudur:

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

çeşitli diğer olasılıklarla, örneğin arr.indexOf(el) >= 0veya hatta ~arr.indexOf(el).

Bu modeller iki problemi ortaya çıkarır:

  • "Ne demek istediğinizi söyleyemiyorlar": dizinin bir öğe içerip içermediğini sormak yerine, dizideki o öğenin ilk oluşum indeksinin ne olduğunu sorarsınız ve sonra onu karşılaştırırsınız veya onu bit çevirerek asıl sorunuzun cevabı.
  • Onlar için başarısız NaNolarak, indexOfböylece Sıkı Eşitlik Karşılaştırma ve kullanır [NaN].indexOf(NaN) === -1.

Önerilen çözüm

Array.prototype.includesYukarıdaki modellerin şu şekilde yeniden yazılabileceği şekilde bir yöntemin eklenmesini öneriyoruz.

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

Bu, Katı Eşitlik Karşılaştırması yerine SameValueZero karşılaştırma algoritmasını kullanması dışında yukarıdakilerle hemen hemen aynı semantiğe sahiptir, böylece [NaN].includes(NaN)doğru hale gelir .

Böylece bu öneri, mevcut kodda görülen her iki sorunu da çözer.

Ek olarak tutarlılık fromIndexiçin Array.prototype.indexOfve benzeri bir parametre ekliyoruz String.prototype.includes.


Daha fazla bilgi:


1
Gerçeğin sadece yarısı. Ayrıca farklıdır: eksik öğeler undefinedtarafından değerlendirilir .includes()ve dikkate alınmaz .indexOf().
Robert Siemer

11

Performansları merak ediyorsanız, şu an için indexOf daha hızlıdır, ancak bu JSperf testi, zaman geçtikçe daha includes()hızlı olacağını gösterme eğilimindedir indexOf(sanırım daha fazla optimize edilecektir).

IMHO, ayrıca if (arr.includes(el)) {}daha net ve daha sürdürülebilir olduğu için yazmayı tercih ediyorum.if (arr.indexOf(el) !== -1) {}


1
Görünüşe göre performanstaki fark o kadar da açık değil. Mobil Firefox'um indexOf'un aslında daha hızlı olduğunu gösteriyor. Bazı Chrome sürümleri aynı şekilde davranır ... Ancak bugünün uygulamalarında fark zaten önemsiz görünüyor.
Nux

8

.indexOf()ve .includes()yöntemler, bir dizideki bir öğeyi aramak veya belirli bir dizede bir karakter / alt dizeyi aramak için kullanılabilir.

Dizide Kullanım

( ECMAScript Spesifikasyonuna Bağlantı )

  1. indexOfkullanan Katı eşitlik karşılaştırma iken, includeskullanım SameValueZero algoritması. Bu nedenle aşağıdaki iki nokta farklılıklar ortaya çıkar.

  2. Felix Kling'in belirttiği gibi , durumda davranış farklıdır NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. Davranış olması durumunda da farklıdır undefined.
let arr = [ , , ];

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

Dizede Kullanım

( ECMAScript Spesifikasyonuna Bağlantı )

  1. Bir RegExp'e iletirseniz indexOf, RegExp'i bir dize olarak değerlendirir ve bulunursa, dizenin dizinini döndürür. Ancak, bir RegExp'e iletirseniz includes, bir istisna atar.
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

Verim

538ROMEO'nun işaret ettiği gibi , includesbiraz (çok küçük) biraz daha yavaş olabilir (çünkü ilk argüman olarak bir normal ifadeyi kontrol etmesi gerekir), indexOfancak gerçekte bu çok fazla fark yaratmaz ve ihmal edilebilir.

Tarih

String.prototype.includes()ECMAScript 2015'te Array.prototype.includes()tanıtıldı, ECMAScript 2016'da tanıtıldı. Tarayıcı desteği ile ilgili olarak, bunları akıllıca kullanın.

String.prototype.indexOf()ve Array.prototype.indexOf()ECMAScript'in ES5 sürümünde mevcuttur ve bu nedenle tüm tarayıcılar tarafından desteklenir.


indexOftrueaçıkça undefinedbir diziye girdikten sonra verir : let arr=[undefined];or let arr=[];arr[0]=undefined;Nowarr.indexOf(undefined) === 0
Jay Dadhania

Farkı gösteren tek kişi sizsiniz undefined: Nedeni, .includeseksik unsurları görmezden undefinedgelirken .indexOf()onları yok saymasıdır. Eksik öğeleri ile de "oluşturabilirsiniz" arr[number beyond length] = whatever.
Robert Siemer

Kimse ip istemiyordu, ama sizin yorumlarınız .includes()sadece ipleri yediğini gösteriyor . Gerçekte her iki yöntem de her şeyi yapabildikleri kadar iyi bir dizgeye zorlar. Regex özel olarak argüman olarak hariçtir .includes()için standarda gelecek eklemeler izin anki taslağa göre.
Robert Siemer

4

Kavramsal olarak, indexOf konumunu kullanmak istediğinizde indexOf'u kullanmalısınız, yalnızca değeri çıkarmanızı veya dizi üzerinde işlem yapmanızı sağlar, yani öğenin konumunu aldıktan sonra dilim, kaydırma veya bölme kullanarak. Öte yandan, Array. Kullan, ilgilenmediğiniz için değerin dizinin içinde olup olmadığını ve konumun içinde olmadığını bilmeyi içerir.


0

indexOf()ve includes()her ikisi de bir dizideki öğeleri bulmak için kullanılabilir, ancak her işlev farklı dönüş değerleri verir.

indexOfbir sayı döndürür ( -1dizide öğe yoksa veya öğe varsa dizi konumu).

includes()bir boole değeri ( trueveya false) döndürür .


Merhaba Kruti, bu soru zaten cevaplandı ve kabul edilmiş bir cevabı var. Ayrıca, cevabınızın yalnızca diğer cevaplarda zaten söylenmiş olan bilgileri içerdiğini görebilirsiniz. Sonunda soru zaten 4 yaşında. Lütfen en yeni veya cevaplanmamış sorular için rehberlik sağlayın. Teşekkür ederim
leonardfactory
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.