Цикл for of в Javascript — один цикл, чтобы управлять всем

Цикл for of в Javascript - один цикл, чтобы управлять всем

От автора: долгое время for in и for были основными циклами, которые можно было использовать для перебора наборов вещей в JavaScript. Позже мы получили некоторые методы массива, такие как forEach, map, filter и т.д. Все начинает становиться немного запутанным, когда мы используем каждый тип цикла.

Например, вы не можете использовать for in для массивов, только для объектов. Тогда, как мне обработать через цикл объект? Ну, вы можете использовать for in, но только если вы проверите hasOwnProperty или что-то еще, или использовать…

Object.keys(obj).map((key) => { const value = map[key];
});

Что странно, потому что вы должны получить ключи, затем взять значение и т. д. Теперь у нас есть новая вещь под названием ES6 for of. Он все больше и больше используется, поскольку информированность о том, как это делать, увеличивается, но все еще время от времени возникает путаница относительно того, как и когда его применять. Ниже приведено краткое описание некоторых способов использования for of — одного цикла для управления всем.

Массивы

const arrayOfStuff = ['thing one', 'thing two', 'thing three']; for (const thing of arrayOfStuff) { console.log(thing);
}

Для массивов это довольно просто. Это выглядит как for in, но вы не можете применить for in для массива. Суть в том, что thing становится каждым элементом в массиве.

Массивы объектов

const arrayOfObjectsOfStuff = [{ name: 'thing one' }, {name: 'thing two' }, { name: 'thing three' }]; for (const { name } of arrayOfObjectsOfStuff) { console.log(name);
}

Здесь вы заметите, что при итерации массива объектов вы можете использовать деструктурирование, чтобы получить значение ключа name для каждого элемента в массиве. Обратите внимание, что здесь используется дескруктурирование {}, потому что мы дескруктурируем объект, а не [], как в случае дескруктурирования массива.

Объекты

const userMap = { '123': 'user 1', '456': 'user 2', '789': 'user 3',
}; for (const [ id, name ] of Object.entries(userMap)) { console.log(id, name);
}

Здесь все становится еще круче, благодаря магии Object.entries. Object.entries возвращает массив пар ключ-значение, поэтому в данном случае мы получаем…

[ [123, 'user 1'], [456, 'user 2'], [789, 'user 3'],
]

Итак, вы в одной строке конвертируете объект в массив значений ключа, а затем используете деструктурирование для получения значений идентификатора и имени!

Map

const actualMapOfUsers = new Map(); actualMapOfUsers.set('123', 'user 1');
actualMapOfUsers.set('456', 'user 2');
actualMapOfUsers.set('7899', 'user 3'); for (const [id, name] of Array.from(actualMapOfUsers)) { console.log(id, name);
}

С помощью объектов ES6 Map вы можете просто использовать метод Array.from для преобразования Map в, как вы уже догадались, снова массив пар ключей-значений.

Промисы

const getUser = async (name) => { const response = await fetch(`https://api.github.com/users/${name}`); const json = await response.json(); return json;
}; const arrayOfPromises = []; const usernames = ['jcreamer898', 'kwelch', 'AlexSwensen'];
for (const user of usernames) { arrayOfPromises.push(getUser(user));
} Promise.all(arrayOfPromises).then((users) => { for (const user of users) { console.log(user.name); }
});

Последняя крутая вещь, которую вы можете сделать, это обрабатывать промисы или async / await внутри циклов for of. В приведенном выше примере мы на самом деле создаем массив промисов, с помощью которого затем разрешаем Promise.all, так что это добавит кучу вещей в цикл обработки событий, а затем, когда все они будут разрешены, мы вызываем .then для Promise.all.

Обратите внимание, что в этом случае нет использования async / await, поэтому код будет транспилирован в намного меньший, чем в случае кода, который потребует полифилла babel и т. п. от использования async / await. Тем не менее, вы, вероятно, уже установили полифилл, такой как babel, так что в качестве альтернативы вы все еще можете выполнить async / awit Promise.all с помощью…

const main = async () => { const users = await Promise.all(arrayOfPromises);
};

Другой вариант — использовать await в качестве функции async и фактически await каждый ответ.

const getUser = async (name) => { const response = await fetch(`https://api.github.com/users/${name}`); const json = await response.json(); return json;
}; const getUsers = async () => { const users = []; const usernames = ['jcreamer898', 'kwelch', 'AlexSwensen']; for (const name of usernames) { const user = await getUser(name); users.push(user); } return users;
}; const main = async () => { await getUsers();
};

В этом случае код будет приостановлен и будет ждать возвращения getUser каждого ответа, прежде чем перейти к следующему. Вот codesandbox, в котором вы можете увидеть, как все это работает!

Надеемся, что эта статья поможет вам лучше понять цикл for of.

Автор: Jonathan Creamer

Источник: https://www.jonathancreamer.com

Редакция: Команда webformyself.