PorównaniePorównania

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.

Na tej stronie

Porównanie w tabeli

#
  • Co podaje w każdym obrocie

    for...of
    Kolejną wartość
    for...in
    Kolejną nazwę właściwości (napis)
  • Działa na tablicach

    for...of
    Tak, to naturalny wybór
    for...in
    Technicznie tak, ale zwraca indeksy jako napisy
  • Działa na zwykłych obiektach

    for...of
    Nie, obiekt nie jest iterowalny
    for...in
    Tak, to jego główne zastosowanie
  • Właściwości odziedziczone z prototypu

    for...of
    Bez znaczenia, iteruje tylko wartości
    for...in
    Uwzględnia je, trzeba filtrować przez Object.hasOwn()
  • break, continue, await

    for...of
    Wszystkie trzy działają
    for...in
    break i continue działają, await nie
  • Typowe użycie

    for...of
    Tablice, Map, Set, napisy, NodeList
    for...in
    Rzadkie, prościej Object.keys() z for...of

Przykład

#
JavaScript
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)
}
Konsola
string 0
string 1
string 2
Lekcja 1
Lekcja 2
Lekcja 3

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

#
Składnia
for (const value of iterable) {
  // instrukcje
}
for (const key in object) {
  // instrukcje
}

Więcej przykładów

#
for...in na tablicy: pułapka z indeksami
JavaScript
const points = [10, 20, 30]

for (const index in points) {
  console.log(index + 1)
}

for (const [index] of points.entries()) {
  console.log(index + 1)
}
Konsola
01
11
21
1
2
3

W for...in indeks jest napisem, więc + 1 skleja tekst. for...of z entries() daje liczbowy indeks, więc dodawanie działa normalnie.

Obiekt: for...in kontra Object.entries()
JavaScript
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)
}
Konsola
name Kuba
level 4
name Kuba
level 4

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 (albo forEach(), map()). for...in na tablicy to częsta przyczyna trudnych do znalezienia błędów.
  • Potrzebujesz kluczy obiektu w pętli for...of? Użyj Object.keys() albo Object.entries(), nie musisz wtedy sprawdzać Object.hasOwn().
  • Z await w pętli po tablicy asynchronicznych operacji działa tylko for...of.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.