Apakah iterable sama dengan iterator, atau mereka berbeda?
Tampaknya, dari spesifikasinya , iterable adalah objek, katakanlah, obj
sedemikian rupa yang obj[Symbol.iterator]
merujuk ke fungsi, sehingga ketika dipanggil, mengembalikan objek yang memiliki next
metode yang dapat mengembalikan {value: ___, done: ___}
objek:
function foo() {
let i = 0;
const wah = {
next: function() {
if (i <= 2) return { value: (1 + 2 * i++), done: false }
else return { value: undefined, done: true }
}
};
return wah; // wah is iterator
}
let bar = {} // bar is iterable
bar[Symbol.iterator] = foo;
console.log([...bar]); // [1, 3, 5]
for (a of bar) console.log(a); // 1 3 5 (in three lines)
Jadi dalam kode di atas, bar
apakah iterable, dan wah
iterator, dan itu next()
adalah antarmuka iterator.
Jadi, iterable dan iterator adalah hal yang berbeda.
Sekarang, dalam contoh umum generator dan iterator:
function* gen1() {
yield 1;
yield 3;
yield 5;
}
const iter1 = gen1();
console.log([...iter1]); // [1, 3, 5]
for (a of iter1) console.log(a); // nothing
const iter2 = gen1();
for (a of iter2) console.log(a); // 1 3 5 (in three lines)
console.log(iter1[Symbol.iterator]() === iter1); // true
Dalam kasus di atas, gen1
generator, dan iter1
iterator, dan iter1.next()
akan melakukan pekerjaan yang tepat. Tetapi iter1[Symbol.iterator]
apakah memberikan fungsi itu, ketika dipanggil, memberikan kembali iter1
, yang merupakan iterator. Jadi iter1
apakah keduanya iterable dan iterator dalam kasus ini?
Selain itu, iter1
berbeda dari contoh 1 di atas, karena iterable pada contoh 1 dapat memberikan [1, 3, 5]
sebanyak yang diinginkan menggunakan [...bar]
, sementara iter1
iterable, tetapi karena ia mengembalikan dirinya sendiri, yang merupakan iterator yang sama setiap kali, hanya akan memberikan [1, 3, 5]
satu kali.
Jadi kita dapat mengatakan, untuk iterable bar
, berapa kali dapat [...bar]
memberikan hasil [1, 3, 5]
- dan jawabannya adalah, itu tergantung. Dan apakah iterable sama dengan iterator? Dan jawabannya adalah, mereka adalah hal yang berbeda, tetapi mereka bisa sama, ketika iterable menggunakan dirinya sebagai iterator. Apakah itu benar?
sumber
iter1
apakah keduanya iterable dan iterator dalam kasus ini? " - ya. Semua iterator asli juga dapat diubah dengan mengembalikan diri mereka sendiri, sehingga Anda dapat dengan mudah mengirimkannya ke dalam konstruksi yang mengharapkan iterable.Jawaban:
Ya, iterables dan iterator adalah hal yang berbeda, tetapi sebagian besar iterator (termasuk semua yang Anda dapatkan dari JavaScript itu sendiri, seperti dari
keys
atauvalues
metode padaArray.prototype
atau generator dari fungsi generator) mewarisi dari objek % IteratorPrototype% , yang memilikiSymbol.iterator
metode seperti ini:Hasilnya adalah semua iterator standar juga dapat diubah. Itu sehingga Anda dapat menggunakannya secara langsung, atau menggunakannya dalam
for-of
loop dan semacamnya (yang mengharapkan iterables, bukan iterator).Pertimbangkan
keys
metode array: Ini mengembalikan iterator array yang mengunjungi kunci array (indeksnya, sebagai angka). Perhatikan bahwa ia mengembalikan iterator . Tetapi penggunaan umum dari itu adalah:for-of
mengambil iterable , bukan iterator , jadi mengapa itu berhasil?Ini bekerja karena iterator juga dapat diubah;
Symbol.iterator
baru saja kembalithis
.Berikut adalah contoh yang saya gunakan dalam Bab 6 buku saya: Jika Anda ingin mengulang semua entri tetapi melewati yang pertama dan Anda tidak ingin menggunakan
slice
untuk memotong subset, Anda bisa mendapatkan iterator, baca nilai pertama, lalu serahkan kefor-of
loop:Perhatikan bahwa ini semua iterator standar . Kadang-kadang orang menunjukkan contoh iterator yang dikodekan secara manual seperti ini:
Tampilkan cuplikan kode
Iterator dikembalikan oleh
range
ada tidak sebuah iterable, sehingga gagal ketika kita mencoba untuk menggunakannya denganfor-of
.Untuk membuatnya lebih baik, kita harus:
Symbol.iterator
metode di awal jawaban di atas, atauSayangnya, TC39 memutuskan untuk tidak memberikan cara langsung untuk mendapatkan objek% IteratorPrototype%. Ada cara tidak langsung (mendapatkan iterator dari array, lalu mengambil prototipe-nya, yang didefinisikan sebagai% IteratorPrototype%), tetapi itu menyebalkan.
Tapi toh tidak perlu menulis iterator secara manual seperti itu; cukup gunakan fungsi generator, karena generator yang dikembalikannya dapat diubah:
Tampilkan cuplikan kode
Sebaliknya, tidak semua iterables adalah iterator. Array bisa diubah, tetapi bukan iterator. Begitu juga string, Peta, dan Set.
sumber
Saya menemukan bahwa ada beberapa definisi istilah yang lebih tepat, dan ini adalah jawaban yang lebih pasti:
Menurut Spesifikasi ES6 dan MDN :
Kapan kita punya
foo
disebut fungsi generator . Dan ketika kita punyabar
adalah objek generator . Dan objek generator sesuai dengan protokol iterable dan protokol iterator .Versi yang lebih sederhana adalah antarmuka iterator, yang hanya sebuah
.next()
metode.Protokol iterable adalah: untuk objek
obj
,obj[Symbol.iterator]
memberikan "fungsi argumen nol yang mengembalikan objek, sesuai dengan protokol iterator".Dengan judul tautan MDN , sepertinya kita juga bisa menyebut objek generator sebagai "generator".
Perhatikan bahwa dalam buku Nicolas Zakas, Understanding ECMAScript 6 , ia mungkin secara longgar menyebut "fungsi generator" sebagai "generator", dan "objek generator" sebagai "iterator". Yang perlu diperhatikan adalah, keduanya benar-benar terkait "generator" - satu adalah fungsi generator, dan satu lagi adalah objek generator, atau generator. Objek generator sesuai dengan protokol iteratable dan protokol iterator.
Jika itu hanya objek yang sesuai dengan protokol iterator , Anda tidak dapat menggunakan
[...iter]
ataufor (a of iter)
. Itu harus menjadi objek yang sesuai dengan protokol iterable .Dan kemudian, ada juga kelas Iterator baru, dalam spesifikasi JavaScript masa depan yang masih dalam konsep . Memiliki antarmuka yang lebih besar, termasuk metode seperti
forEach
,map
,reduce
dari antarmuka Array saat ini, dan yang baru, seperti dantake
, dandrop
. Iterator saat ini merujuk ke objek hanya dengannext
antarmuka.Untuk menjawab pertanyaan awal: apa perbedaan antara iterator dan iterable, jawabannya adalah: iterator adalah objek dengan antarmuka
.next()
, dan iterable adalah objekobj
yangobj[Symbol.iterator]
dapat memberikan fungsi argumen-nol yang, ketika dipanggil, mengembalikan iterator.Dan generator adalah iterable dan iterator, untuk menambah itu.
sumber