Brakuje mi tu kontekstu i boję się, że coś Ci źle podpowiem...
Czy engineFinalObjects
to na pewno tablica? Bo może to zwykły obiekt (wtedy użycie for-in jest OK!).
Jeśli engineFinalObjects
to tablica, to czemu są w niej dziury? Czasami świadczy to o tym, że coś jest źle zaplanowane -- ale też nie zawsze.
Jeśli iterujesz po rzadkiej (ang. sparse) tablicy, to możesz użyć zawsze czegoś takiego:
for (var i = 0; i < arr.length; i++) {
if (arr.hasOwnProperty(i)) {
// operuj na arr[i];
}
}
Język gwarantuje, że length
będzie ustawione na najwyższy indeks tablicy + 1 (ale działa to tylko dla tablic i indeksów liczbowych!). Z kolei wywołanie .hasOwnProperty()
gwarantuje, że przetworzymy tylko te indeksy w tablicy, które istnieją -- więc pominiemy dziury.
Tyle że jeśli masz bardzo rzadką tablicę, to powyższe rozwiązanie będzie nieefektywne (dużo niepotrzebnych wywołań .hasOwnProperty()).
Może faktycznie być tak, że spotkałeś się z tą wyjątkową sytuacją, w której najlepszym praktycznym wyjściem będzie użycie for-in na tablicy. Jeśli chcesz ochronić taką pętlę przed odziedziczonymi własnościami, to także możesz użyć hasOwnProperty
:
for (var key in engineFinalObjects) {
if (engineFinalObjects.hasOwnProperty(key)) {
var value = engineFinalObjects[key];
console.log(key, value);
}
}
Często się zdarza, że ludzie używają for-in tylko dlatego, że dla nich to to samo co odpowiednie dla tablic for-each -- a są w błędzie. Dlatego chciałem Cię przestrzec.
Jeśli pisałbyś tylko pod nowoczesne przeglądarki (czyli niestety nie IE8), mógłbyś użyć funkcji forEach
, które mają tablice zgodnie ze specyfikacją ECMAScriptu 5:
engineFinalObjects.forEach(function(value) {
console.log(value);
});
Czyli to coś takiego jak pętla foreach. Tak naprawdę, funkcja przekazana do forEach
dostaje jeszcze za parametr indeks elementu tablicy i samą tablicę, ale nie musisz pisać tych parametrów gdy ich nie potrzebujesz. Pełna sygnatura wygląda jednak tak:
engineFinalObjects.forEach(function(value, index, arr) {
console.log(value);
});
Ostrzegę Cię jeszcze przed dwoma rzeczami:
- Zawsze deklaruj zmienne używając
var
. W pierwszym poście masz to var
pominięte. Powinno być for (var obj in...)
lub obj
powinno zostać zadeklarowane gdzieś wyżej. Jeśli pominiesz var
, zmienna obj
będzie globalna.
- Wiem, że to żałosne, ale w JavaScripcie istnieje "jedyny słuszny" sposób stawiania klamr otaczających bloki instrukcji warunkowych, pętli itp. Nie powinno się stawiać klamry otwierającej w nowej linii. W JS-ie działa automatyczne wstawianie średników (tm) i daje się ono we znaki, jeśli będziesz chciał zwrócić z funkcji literał obiektowy, ale postawisz klamrę w nowej linii. Napiszesz:
return
{
foo: 123
};
...a po automatycznym wstawieniu średnika zostanie to zamienione na:
return;
{
foo: 123
};
co jest równorzędne z:
return undefined;
{
foo: 123
};
i funkcja zwróci Ci undefined
;). A dalsza część funkcji (to, co miało być literałem obiektowym) będzie potraktowana jako martwy kod. Tak piszę żebyś się nie zdziwił gdy na to natrafisz.