for. . . in vs for. . . of
for...of podaje kolejne wartości obiektu iterowalnego, a for...in kolejne nazwy właściwości obiektu jako napisy.
Porównanie w tabeli
#Co podaje w każdym obrocie
Działa na tablicach
Działa na zwykłych obiektach
Właściwości odziedziczone z prototypu
break, continue, await
Typowe użycie
Przykład
#const tasks = ['Lekcja 1', 'Lekcja 2', 'Lekcja 3']
for (const index in tasks) {
console.log(typeof index, index)
}
for (const task of tasks) {
console.log(task)
}Definicja i zastosowanie
#Obie pętle w każdym obrocie podają coś innego. for...of działa na obiektach iterowalnych, takich jak tablice, napisy, Map i Set, i zwraca kolejną wartość. for...in działa na zwykłych obiektach i zwraca kolejną nazwę właściwości (klucz) jako napis, a samą wartość odczytujesz dodatkowo przez object[key].
Na tablicy for...in też technicznie zadziała, ale zwraca indeksy jako napisy ("0", "1") i oprócz nich może złapać dodatkowe właściwości wyliczalne, w tym odziedziczone z prototypu. for...of tego problemu nie ma, bo iteruje same wartości, a dodatkowo wspiera break, continue i await w środku, czego for...in do końca nie wspiera.
Zasada jest prosta: do tablic, napisów i innych obiektów iterowalnych używaj for...of. for...in zostaw do rzadkich sytuacji z obiektami, których kształtu nie znasz z góry, a nawet tam często wygodniejsze jest Object.keys() lub Object.entries() razem z for...of.
Składnia
#for (const value of iterable) {
// instrukcje
}
for (const key in object) {
// instrukcje
}Więcej przykładów
#const points = [10, 20, 30]
for (const index in points) {
console.log(index + 1)
}
for (const [index] of points.entries()) {
console.log(index + 1)
}W for...in indeks jest napisem, więc + 1 skleja tekst. for...of z entries() daje liczbowy indeks, więc dodawanie działa normalnie.
const student = { name: 'Kuba', level: 4 }
for (const key in student) {
console.log(key, student[key])
}
for (const [key, value] of Object.entries(student)) {
console.log(key, value)
}Dla prostego obiektu bez odziedziczonych właściwości obie pętle dają ten sam wynik. Object.entries() zwraca jednak tylko własne klucze, więc jest bezpieczniejsze.
Dobre praktyki
#- Do tablic zawsze wybieraj
for...of(alboforEach(),map()).for...inna tablicy to częsta przyczyna trudnych do znalezienia błędów. - Potrzebujesz kluczy obiektu w pętli
for...of? UżyjObject.keys()alboObject.entries(), nie musisz wtedy sprawdzaćObject.hasOwn(). - Z
awaitw pętli po tablicy asynchronicznych operacji działa tylkofor...of.
Powiązane hasła
#- for...ofPrzechodzi po kolejnych wartościach obiektu iterowalnego: tablicy, napisu, Map, Set i innych.
- for...inPrzechodzi po nazwach wyliczalnych właściwości obiektu, także tych odziedziczonych z prototypu.
- Object.entries()Zwraca tablicę par [klucz, wartość] obiektu.
- Object.keys()Zwraca tablicę nazw własnych, wyliczalnych właściwości obiektu.
- Array.prototype.forEach()Wywołuje funkcję dla każdego elementu tablicy.
Widzisz błąd albo brakuje przykładu? Napisz do nas.