Saya akan mencoba ini. Perhatikan bahwa saya tidak berafiliasi dengan ECMA dan tidak dapat melihat proses pengambilan keputusan mereka, jadi saya tidak dapat secara pasti mengatakan mengapa mereka telah atau belum melakukan apa pun. Namun, saya akan menyatakan asumsi saya dan melakukan yang terbaik.
1. Mengapa menambahkan for...ofkonstruksi di tempat pertama?
JavaScript sudah menyertakan for...inkonstruksi yang dapat digunakan untuk mengulang properti suatu objek. Namun, ini sebenarnya bukan perulangan forEach , karena ia menyebutkan semua properti pada sebuah objek dan cenderung hanya bekerja dengan diprediksi dalam kasus sederhana.
Ini rusak dalam kasus yang lebih kompleks (termasuk dengan larik, di mana penggunaannya cenderung tidak disarankan atau sepenuhnya dikaburkan oleh pengamanan yang diperlukan untuk digunakan for...indengan larik dengan benar ). Anda dapat mengatasinya dengan menggunakan hasOwnProperty(antara lain), tetapi itu agak kikuk dan tidak elegan.
Jadi oleh karena itu asumsi saya adalah bahwa for...ofkonstruksi sedang ditambahkan untuk mengatasi kekurangan yang terkait dengan for...inkonstruksi tersebut, dan memberikan utilitas dan fleksibilitas yang lebih besar saat melakukan iterasi. Orang cenderung memperlakukan for...insebagai forEachloop yang secara umum dapat diterapkan pada koleksi apa pun dan menghasilkan hasil yang waras dalam konteks yang memungkinkan, tetapi bukan itu yang terjadi. The for...ofLoop perbaikan itu.
Saya juga berasumsi bahwa penting untuk kode ES5 yang ada untuk berjalan di bawah ES6 dan menghasilkan hasil yang sama seperti di bawah ES5, jadi perubahan yang melanggar tidak dapat dilakukan, misalnya, pada perilaku for...inkonstruksi.
2. Bagaimana cara for...ofkerjanya?
The dokumentasi referensi berguna untuk bagian ini. Secara spesifik, sebuah objek dipertimbangkan iterablejika ia mendefinisikan Symbol.iteratorproperti.
Definisi properti harus berupa fungsi yang mengembalikan item dalam koleksi, satu, oleh, satu, dan menyetel bendera yang menunjukkan apakah ada lebih banyak item untuk diambil atau tidak. Implementasi yang telah ditentukan disediakan untuk beberapa tipe objek , dan cukup jelas bahwa for...ofhanya menggunakan delegasi ke fungsi iterator.
Pendekatan ini berguna, karena membuatnya sangat mudah untuk menyediakan iterator Anda sendiri. Saya dapat mengatakan bahwa pendekatan tersebut dapat menyajikan masalah praktis karena ketergantungannya pada pendefinisian properti yang sebelumnya tidak ada, kecuali dari apa yang dapat saya katakan bukan itu masalahnya karena properti baru pada dasarnya diabaikan kecuali Anda sengaja mencarinya (mis. itu tidak akan muncul dalam for...inloop sebagai kunci, dll.). Jadi bukan itu masalahnya.
Terlepas dari non-masalah praktis, mungkin telah dianggap kontroversial secara konseptual untuk memulai semua objek dengan properti baru yang telah ditentukan sebelumnya, atau secara implisit mengatakan bahwa "setiap objek adalah koleksi".
3. Mengapa objek tidak iterabledigunakan for...ofsecara default?
Dugaan saya adalah bahwa ini adalah kombinasi dari:
- Membuat semua objek
iterablesecara default mungkin dianggap tidak dapat diterima karena menambahkan properti yang sebelumnya tidak ada, atau karena objek tidak (harus) merupakan koleksi. Seperti yang Felix catat, "apa artinya mengulang fungsi atau objek ekspresi reguler"?
- Objek sederhana sudah dapat diulang menggunakan
for...in, dan tidak jelas apa implementasi iterator built-in bisa dilakukan secara berbeda / lebih baik dari for...inperilaku yang ada . Jadi, meskipun # 1 salah dan menambahkan properti dapat diterima, mungkin tidak terlihat berguna .
- Pengguna yang ingin membuat objeknya
iterabledapat dengan mudah melakukannya, dengan mendefinisikan Symbol.iteratorproperti.
- Spesifikasi ES6 juga menyediakan tipe Peta , yang secara
iterable default dan memiliki beberapa keuntungan kecil lainnya dibandingkan menggunakan objek biasa sebagai Map.
Bahkan ada contoh yang diberikan untuk # 3 dalam dokumentasi referensi:
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
for (var value of myIterable) {
console.log(value);
}
Mengingat bahwa objek dapat dengan mudah dibuat iterable, bahwa mereka sudah dapat diiterasi menggunakan for...in, dan bahwa ada kemungkinan tidak ada kesepakatan yang jelas tentang apa yang harus dilakukan oleh iterator objek default (jika apa yang dilakukannya dimaksudkan untuk entah bagaimana berbeda dari apa yang for...indilakukannya), tampaknya masuk akal cukup sehingga objek tidak dibuat iterablesecara default.
Perhatikan bahwa kode contoh Anda dapat ditulis ulang menggunakan for...in:
for (let levelOneKey in object) {
console.log(levelOneKey);
console.log(object[levelOneKey]);
var levelTwoObj = object[levelOneKey];
for (let levelTwoKey in levelTwoObj ) {
console.log(levelTwoKey);
console.log(levelTwoObj[levelTwoKey]);
}
}
... atau Anda juga dapat membuat objek iterablesesuai keinginan dengan melakukan sesuatu seperti berikut (atau Anda dapat membuat semua objek iterabledengan menetapkannya Object.prototype[Symbol.iterator]):
obj = {
a: '1',
b: { something: 'else' },
c: 4,
d: { nested: { nestedAgain: true }}
};
obj[Symbol.iterator] = function() {
var keys = [];
var ref = this;
for (var key in this) {
keys.push(key);
}
return {
next: function() {
if (this._keys && this._obj && this._index < this._keys.length) {
var key = this._keys[this._index];
this._index++;
return { key: key, value: this._obj[key], done: false };
} else {
return { done: true };
}
},
_index: 0,
_keys: keys,
_obj: ref
};
};
Anda dapat memainkannya di sini (di Chrome, sewa): http://jsfiddle.net/rncr3ppz/5/
Sunting
Dan sebagai tanggapan atas pertanyaan Anda yang telah diperbarui, ya, dimungkinkan untuk mengonversi sebuah iterablemenjadi larik, menggunakan operator sebaran di ES6.
Namun, ini sepertinya belum berfungsi di Chrome, atau setidaknya saya tidak bisa membuatnya berfungsi di jsFiddle saya. Secara teori, ini harus sesederhana:
var array = [...myIterable];
Symbol.iteratorproperti bersifat iterable. Jadi, Anda hanya perlu menerapkan properti itu. Satu penjelasan yang mungkin mengapa objek tidak dapat diulang bisa jadi bahwa ini menyiratkan semuanya dapat diulang, karena semuanya adalah objek (kecuali primitif tentu saja). Namun, apa artinya mengulang fungsi atau objek ekspresi reguler?