Чому за замовчуванням об’єкти не можна повторити?
Я постійно бачу запитання, пов’язані з ітерацією об’єктів, загальним рішенням є перегляд властивостей об’єкта та доступ до значень в об’єкті таким чином. Це здається настільки звичним, що змушує задуматися, чому самі об’єкти не піддаються ітерації.
Такі твердження, як ES6, for...of
було б непогано використовувати для об'єктів за замовчуванням. Оскільки ці функції доступні лише для спеціальних "ітеративних об'єктів", які не включають {}
об'єкти, нам доведеться пройти обручі, щоб зробити цю роботу для об'єктів, для яких ми хочемо її використовувати.
Оператор for ... створює цикл, що ітератує над ітерабельними об’єктами (включаючи масив, карту, набір, об’єкт аргументів тощо) ...
Наприклад, використовуючи функцію генератора ES6 :
var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
function* entries(obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
for (let [key, value] of entries(example)) {
console.log(key);
console.log(value);
for (let [key, value] of entries(value)) {
console.log(key);
console.log(value);
}
}
Вищевказане належним чином реєструє дані в тому порядку, в якому я очікую, коли я запускаю код у Firefox (який підтримує ES6 ):
За замовчуванням {}
об'єкти не піддаються ітерації, але чому? Чи переважуватимуть недоліки потенційні переваги об'єктів, які можна повторити? Які проблеми пов'язані з цим?
Крім того, оскільки {}
об'єкти відрізняються від «Array-як» колекція і «ітерація об'єктів» , таких як NodeList
, HtmlCollection
і arguments
вони не можуть бути перетворені в масиви.
Наприклад:
var argumentsArray = Array.prototype.slice.call(arguments);
або використовувати з методами Array:
Array.prototype.forEach.call(nodeList, function (element) {})
.
Окрім питань, які у мене є вище, я хотів би побачити робочий приклад того, як зробити {}
об’єкти ітерабельними, особливо від тих, хто згадав про це [Symbol.iterator]
. Це має дозволити цим новим {}
"ітерабельним об'єктам" використовувати оператори типу for...of
. Крім того, мені цікаво, якщо створення об’єктів, які можна повторити, дозволить їх перетворити на масиви.
Я спробував наведений нижче код, але отримав файл TypeError: can't convert undefined to object
.
var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
// I want to be able to use "for...of" for the "example" object.
// I also want to be able to convert the "example" object into an Array.
example[Symbol.iterator] = function* (obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
};
for (let [key, value] of example) { console.log(value); } // error
console.log([...example]); // error
Symbol.iterator
властивість, можна повторити. Тож вам просто потрібно було б реалізувати це властивість. Одне з можливих пояснень, чому об’єкти не піддаються ітерації, може полягати в тому, що це означало б, що все було ітерабельним, оскільки все є об’єктом (крім примітивів, звичайно). Однак, що означає перебирати функцію чи об’єкт регулярного виразу?