Dlaczego jest za pomocą "for...in" z iteracją tablicy to zły pomysł?

Powiedziano mi, aby nie używać for...in z tablicami w JavaScript. Dlaczego nie?

Author: John Slegers, 2009-02-01

25 answers

Powód jest taki, że jedna konstrukcja:

var a = []; // Create a new empty array.
a[5] = 5;   // Perfectly legal JavaScript that resizes the array.

for (var i = 0; i < a.length; i++) {
    // Iterate over numeric indexes from 0 to 5, as everyone expects.
    console.log(a[i]);
}

/* Will display:
   undefined
   undefined
   undefined
   undefined
   undefined
   5
*/

Może być czasem zupełnie inna od drugiej:

var a = [];
a[5] = 5;
for (var x in a) {
    // Shows only the explicitly set index of "5", and ignores 0-4
    console.log(x);
}

/* Will display:
   5
*/

Weź również pod uwagę, że JavaScript biblioteki mogą robić takie rzeczy, co wpłynie na każdą utworzoną tablicę:

// Somewhere deep in your JavaScript library...
Array.prototype.foo = 1;

// Now you have no idea what the below code will do.
var a = [1, 2, 3, 4, 5];
for (var x in a){
    // Now foo is a part of EVERY array and 
    // will show up here as a value of 'x'.
    console.log(x);
}

/* Will display:
   0
   1
   2
   3
   4
   foo
*/
 1374
Author: Triptych,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-09 07:51:46

Instrukcja for-in sama w sobie nie jest "złą praktyką", jednak może być niewłaściwie użyta, na przykład do iteracji nad tablicami lub obiektami przypominającymi tablice.

Celem instrukcji for-in jest wyliczenie nad właściwościami obiektu. To stwierdzenie pojawi się w łańcuchu prototypów, również wyliczając odziedziczone właściwości, rzecz, która czasami nie jest pożądana.

Również kolejność iteracji nie jest gwarantowana przez spec., co oznacza, że jeśli chcemy "iterację" obiektu array, za pomocą tej instrukcji nie możemy być pewni, że właściwości (indeksy tablic) będą wyświetlane w kolejności liczbowej.

Na przykład w JScript (IE

var array = [];
array[2] = 'c';
array[1] = 'b';
array[0] = 'a';

for (var p in array) {
  //... p will be "2", "1" and "0" on IE
}

Ponadto, mówiąc o dziedziczonych właściwościach, jeśli na przykład rozszerzysz obiekt Array.prototype (tak jak niektóre biblioteki jak MooTools), te właściwości będą również

Array.prototype.last = function () { return this[this.length-1]; };

for (var p in []) { // an empty array
  // last will be enumerated
}

Jak już mówiłem do iteracji nad tablicami lub obiektami typu array, najlepiej jest użyć pętli sekwencyjnej , takiej jak zwykły for/while pętla.

Jeśli chcesz wyliczyć tylko własne właściwości obiektu (te, które nie są dziedziczone), możesz użyć metody hasOwnProperty:

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) {
    // prop is not inherited
  }
}

A niektórzy nawet zalecają wywołanie metody bezpośrednio z Object.prototype, aby uniknąć problemów, jeśli ktoś doda właściwość nazwa hasOwnProperty do naszego obiektu:

for (var prop in obj) {
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
    // prop is not inherited
  }
}
 359
Author: CMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-24 17:51:32

Istnieją trzy powody, dla których nie powinieneś używać for..in do iteracji elementów tablicy:

  • for..in spowoduje zapętlenie wszystkich własnych i odziedziczonych właściwości obiektu array, które nie są DontEnum; to oznacza, że jeśli ktoś doda właściwości do konkretnego obiektu array (są ku temu ważne powody - sam to zrobiłem) lub zmieni Array.prototype (co jest uważane za złą praktykę w kodzie, który ma działać dobrze z innymi skryptami), te właściwości będą również iterowane; dziedziczone właściwości można wykluczyć, sprawdzając hasOwnProperty(), ale nie pomoże to w przypadku właściwości ustawionych w samym obiekcie array

  • for..in nie gwarantuje zachowania kolejności elementów

  • Jest to powolne, ponieważ musisz przejść wszystkie właściwości obiektu array i całego łańcucha prototypów i nadal pobierze tylko nazwę właściwości, tzn. aby uzyskać wartość, wymagane będzie dodatkowe wyszukiwanie

 101
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-01 14:16:38

Ponieważ for...in wylicza poprzez obiekt, który przechowuje tablicę, a nie samą tablicę. Jeśli dodam funkcję do łańcucha prototypów tablic, będzie ona również uwzględniona. I. E.

Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
 document.write(x + ' = ' + a[x]);
}

To napisze:

0 = foo
1 = bar
myOwnFunction = function() { alert(this); }

A ponieważ nigdy nie możesz być pewien, że nic nie zostanie dodane do łańcucha prototypów, użyj pętli for, aby wyliczyć tablicę:

for(i=0,x=a.length;i<x;i++){
 document.write(i + ' = ' + a[i]);
}

To napisze:

0 = foo
1 = bar
 49
Author: Pim Jager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-14 13:41:06

W izolacji, nie ma nic złego w używaniu for-in na tablicach. For-in iteruje nad nazwami właściwości obiektu, a w przypadku tablicy" out-of-the-box", właściwości odpowiadają indeksom tablicy. (Wbudowane propertes jak length, toString i tak dalej nie są uwzględniane w iteracji.)

Jeśli jednak Twój kod (lub framework, którego używasz) doda własne właściwości do tablic lub do prototypu tablicy, wtedy te właściwości zostaną uwzględnione w iteracji, która pewnie tego nie chcesz.

Niektóre frameworki JS, takie jak Prototype modyfikują prototyp tablicy. Inne frameworki jak JQuery Nie, więc z JQuery można bezpiecznie używać for-in.

Jeśli masz wątpliwości, prawdopodobnie nie powinieneś używać for-in.

Alternatywnym sposobem iteracji przez tablicę jest użycie pętli for:

for (var ix=0;ix<arr.length;ix++) alert(ix);

Ma to jednak inny problem. Problem polega na tym, że tablica JavaScript może mieć "dziury". Jeśli zdefiniujesz arr jako:

var arr = ["hello"];
arr[100] = "goodbye";

Wtedy tablica ma dwa elementy, ale długość 101. Użycie for-in Da dwa indeksy, podczas gdy for-loop da 101 indeksów, gdzie 99 ma wartość undefined.

 37
Author: JacquesB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-23 21:28:25

Oprócz powodów podanych w innych odpowiedziach, możesz nie chcieć używać "for...in" struktura jeśli trzeba wykonać matematykę ze zmienną counter, ponieważ pętla Itera się poprzez nazwy właściwości obiektu, a więc zmienna jest ciągiem znaków.

Na przykład,

for (var i=0; i<a.length; i++) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

Napisze

0, number, 1
1, number, 2
...

for (var ii in a) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

Napisze

0, string, 01
1, string, 11
...

Oczywiście można to łatwo przezwyciężyć, włączając

ii = parseInt(ii);

W pętli, ale pierwsza struktura jest bardziej bezpośredni.

 29
Author: ctmiddle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-02 02:29:46

Od 2016 (ES6) możemy używać for…of do iteracji tablicy, jak zauważył John Slegers.

Chciałbym tylko dodać ten prosty kod demonstracyjny, aby wszystko było jaśniejsze:

Array.prototype.foo = 1;
var arr = [];
arr[5] = "xyz";

console.log("for...of:");
var count = 0;
for (var item of arr) {
    console.log(count + ":", item);
    count++;
    }

console.log("for...in:");
count = 0;
for (var item in arr) {
    console.log(count + ":", item);
    count++;
    }

Konsola pokazuje:

for...of:

0: undefined
1: undefined
2: undefined
3: undefined
4: undefined
5: xyz

for...in:

0: 5
1: foo

Innymi słowy:

  • for...of liczy od 0 do 5, a także ignoruje Array.prototype.foo. Pokazuje tablicę wartości .

  • for...in wyświetla tylko 5, ignorując niezdefiniowane indeksy tablicy, ale dodając foo. Pokazuje tablicę nazwy nieruchomości .

 26
Author: MarcG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-10 04:29:37

Pomijając fakt, że for...in pętle nad wszystkimi właściwościami wyliczeniowymi (co jest , a nie tym samym co "wszystkie elementy tablicy"!), zobacz http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf , sekcja 12.6.4 (wydanie piąte) lub 13.7.5.15 (wydanie siódme):

Mechanika i porządek wyliczenia właściwości ... nie jest określone ...

(podkreślenie moje.)

To znaczy, że jeśli przeglądarka chciała, to może przejść przez właściwości w kolejności, w jakiej zostały wstawione. Lub w kolejności numerycznej. Lub w kolejności leksykalnej (gdzie "30" jest przed "4"! Należy pamiętać, że wszystkie klucze obiektów - a zatem wszystkie indeksy tablicy - są w rzeczywistości łańcuchami, więc ma to sens). Może przejść przez nie przez bucket, jeśli zaimplementuje obiekty jako tabele hash. Albo weź cokolwiek z tego i dodaj "do tyłu". Przeglądarka może nawet iterować losowo i być zgodna z ECMA-262, o ile odwiedza każdą właściwość dokładnie raz.

W praktyce większość przeglądarek obecnie lubi iterację w mniej więcej tej samej kolejności. Ale nic nie mówi, że muszą. Jest to specyficzna implementacja i może ulec zmianie w dowolnym momencie, jeśli okaże się, że inny sposób jest o wiele bardziej wydajny.

Tak czy inaczej, for...in nie niesie ze sobą żadnych konotacji porządku. Jeśli zależy ci na porządku, bądź o nim szczery i użyj zwykłej pętli for z indeksem.

 21
Author: cHao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 08:55:07

Krótka odpowiedź: po prostu nie warto.


Dłuższa odpowiedź: po prostu nie warto, nawet jeśli kolejność elementów sekwencyjnych i optymalna wydajność nie są wymagane.


Długa odpowiedź: po prostu nie warto, z następujących powodów:

  • użycie for (var i in array) {} spowoduje, że 'array' będzie interpretowany jako dowolny inny czysty obiekt, przemierzając łańcuch właściwości obiektu i ostatecznie wykonując działanie wolniejsze niż pętla for oparta na indeksie.
  • nie ma gwarancji, że zwraca właściwości obiektu w sekwencyjnej kolejności, zgodnie z oczekiwaniami.
  • użycie sprawdzeń hasOwnProperty() lub isNaN() do filtrowania właściwości obiektu jest dodatkowym obciążeniem powodującym, że działa on (jeszcze bardziej) wolniej. Ponadto wprowadzenie takiej dodatkowej logiki neguje w pierwszej kolejności kluczowy powód jej użycia, tj. ze względu na bardziej zwięzły format.

Z tych powodów akceptowalny kompromis między wydajnością a wygodą nawet nie istnieje. Naprawdę, nie ma korzyści, chyba że intencją jest traktowanie tablicy jako obiektu czystego i wykonywanie operacji na właściwościach obiektu array.

 20
Author: WynandB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-04 00:20:42

Ponieważ wylicza przez pola obiektów, a nie indeksy. Możesz uzyskać wartość z indeksem "długość" i wątpię, że tego chcesz.

 15
Author: vava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-01 09:50:03

Głównie z dwóch powodów:

One

Jak mówili inni, możesz otrzymać klucze, których nie ma w tablicy lub które są odziedziczone po prototypie. Jeśli więc, powiedzmy, biblioteka dodaje właściwość do tablicy lub prototypów obiektu:

Array.prototype.someProperty = true

Otrzymasz go jako część każdej tablicy:

for(var item in [1,2,3]){
  console.log(item) // will log 1,2,3 but also "someProperty"
}

Można to rozwiązać metodą hasOwnProperty:

var ary = [1,2,3];
for(var item in ary){
   if(ary.hasOwnProperty(item)){
      console.log(item) // will log only 1,2,3
   }
}

Ale to prawda dla iteracji nad dowolnym obiektem Z for-in pętla.

Dwa

Zwykle kolejność elementów w tablicy jest ważna, ale pętla for-in niekoniecznie będzie iteracją we właściwej kolejności, ponieważ traktuje tablicę jako obiekt, co jest sposobem implementacji w JS, a nie jako tablicę. Wydaje się to małą rzeczą, ale może naprawdę spieprzyć aplikacje i jest trudne do debugowania.

 15
Author: Lior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-04 16:54:16

Problem z for ... in ... - i staje się to problemem tylko wtedy, gdy programista nie do końca rozumie ten język; nie jest to tak naprawdę błąd, czy coś takiego - polega na tym, że iteracje dotyczą wszystkich członków obiektu (cóż, wszystkich wyliczalnych członków, ale to na razie szczegół). Jeśli chcesz iterować nad tylko indeksowanymi właściwościami tablicy, jedynym gwarantowanym sposobem zachowania spójności semantycznej jest użycie indeksu całkowitego (czyli stylu for (var i = 0; i < array.length; ++i) loop).

Każdy obiekt może mieć dowolne właściwości z nim związane. Nie byłoby nic strasznego w wczytywaniu dodatkowych właściwości do instancji tablicy, w szczególności. Kod, który chce widzieć tylko indeksowane właściwości podobne do tablicy, dlatego musi trzymać się indeksu liczb całkowitych. Kod, który jest w pełni świadomy tego, co for ... in robi i naprawdę potrzebuje , aby zobaczyć wszystkie właściwości, cóż, to też jest ok.

 14
Author: Pointy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-06 13:26:19

[[5]] chyba nie mam wiele do dodania np. odpowiedź tryptyku lub odpowiedź CMS NA dlaczego w niektórych przypadkach należy unikać używania for-in.

Chciałbym jednak dodać, że w nowoczesnych przeglądarkach istnieje alternatywa dla for-in, która może być używana w przypadkach, w których nie można użyć for-in. Alternatywą jest for-of :

for (var item of items) {
    console.log(item);
}

Uwaga:

Niestety, żadna wersja Internet Explorera nie obsługuje tej funkcji (Edge 12 + does), więc będziesz musiał poczekać trochę dłużej, aż będziesz mógł go użyć w kodzie produkcyjnym po stronie klienta. Jednakże, powinien być bezpieczny w użyciu w kodzie JS po stronie serwera (jeśli używasz Node.js ).

 10
Author: John Slegers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-08 08:55:53

Również, ze względu na semantykę, sposób, w jaki for, in traktuje tablice (tzn. tak samo jak każdy inny obiekt JavaScript) nie jest zgodny z innymi popularnymi językami.

// C#
char[] a = new char[] {'A', 'B', 'C'};
foreach (char x in a) System.Console.Write(x); //Output: "ABC"

// Java
char[] a = {'A', 'B', 'C'};
for (char x : a) System.out.print(x);          //Output: "ABC"

// PHP
$a = array('A', 'B', 'C');
foreach ($a as $x) echo $x;                    //Output: "ABC"

// JavaScript
var a = ['A', 'B', 'C'];
for (var x in a) document.write(x);            //Output: "012"
 8
Author: matpop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-25 16:43:32

Oprócz innych problemów, "for..in" składnia jest prawdopodobnie wolniejsza, ponieważ indeks jest ciągiem znaków, a nie liczbą całkowitą.

var a = ["a"]
for (var i in a)
    alert(typeof i)  // 'string'
for (var i = 0; i < a.length; i++)
    alert(typeof i)  // 'number'
 7
Author: dc1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-05 22:59:12

Ważnym aspektem jest to, że for...in tylko iteruje nad właściwościami zawartymi w obiekcie, które mają swoje wyliczalne atrybut właściwości ustawiony na true. Jeśli więc ktoś spróbuje iterować nad obiektem używając for...in, wtedy dowolne właściwości mogą zostać pominięte, jeśli ich wartość atrybutu właściwości jest false. Jest całkiem możliwe, aby zmienić atrybut właściwości enumerable dla normalnych obiektów tablicy tak, że pewne elementy nie są wyliczane. Chociaż ogólnie rzecz biorąc atrybuty własności zwykle stosuje się do Właściwości funkcji wewnątrz obiektu.

Można sprawdzić wartość atrybutu właściwości enumerable poprzez:

myobject.propertyIsEnumerable('myproperty')

Lub uzyskanie wszystkich czterech atrybutów własności:

Object.getOwnPropertyDescriptor(myobject,'myproperty')

Jest to funkcja dostępna w ECMAScript 5 - we wcześniejszych wersjach nie można było zmienić wartości atrybutu właściwości enumerable (zawsze była ustawiona na true).

 7
Author: Pierz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-10 18:20:26

The for/in działa z dwoma typami zmiennych: hashtables (tablice asocjacyjne) i array (nie asocjacyjne).

JavaScript automatycznie określi sposób, w jaki przechodzi przez elementy. Więc jeśli wiesz, że Twoja tablica jest naprawdę nie asocjacyjna, możesz użyć for (var i=0; i<=arrayLen; i++) i pominąć iterację automatycznego wykrywania.

Ale moim zdaniem lepiej użyć for/in, proces wymagany do tego automatycznego wykrywania jest bardzo mały.

Prawdziwa odpowiedź na to będzie zależeć od tego, jak przeglądarka parsuje / interpretuje kod JavaScript. Może się zmieniać między przeglądarkami.

Nie mogę myśleć o innych celach, aby nie używać for/in;

//Non-associative
var arr = ['a', 'b', 'c'];
for (var i in arr)
   alert(arr[i]);

//Associative
var arr = {
   item1 : 'a',
   item2 : 'b',
   item3 : 'c'
};

for (var i in arr)
   alert(arr[i]);
 7
Author: Ricardo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-13 01:15:24

TL & DR: używanie pętli for in w tablicach nie jest złe, w rzeczywistości jest wręcz odwrotnie.

Myślę, że pętla for in jest klejnotem JS, jeśli jest używana poprawnie w tablicach. Oczekuje się, że masz pełną kontrolę nad oprogramowaniem i wiesz, co robisz. Zobaczmy wspomniane wady i obalmy je jeden po drugim.

  1. pętli przez dziedziczone właściwości, jak również: przede wszystkim wszelkie rozszerzenia do Array.prototype powinny być wykonane za pomocą Object.defineProperty() a ich deskryptor enumerable powinien być ustawiony na false. Każda biblioteka, która tego nie robi, nie powinna być w ogóle używana.
  2. właściwości te, które dodasz do łańcucha dziedziczenia, zostaną zliczone: {[19] } podczas wykonywania podklasowania tablicy przez Object.setPrototypeOf lub przez klasę extend. Należy ponownie użyć Object.defineProperty(), który domyślnie ustawia writable, enumerable i configurable deskryptory właściwości do false. Pozwala zobaczyć przykład podklasowania tablicy tutaj...

function Stack(...a){
  var stack = new Array(...a);
  Object.setPrototypeOf(stack, Stack.prototype);
  return stack;
}
Stack.prototype = Object.create(Array.prototype);                                 // now stack has full access to array methods.
Object.defineProperty(Stack.prototype,"constructor",{value:Stack});               // now Stack is a proper constructor
Object.defineProperty(Stack.prototype,"peak",{value: function(){                  // add Stack "only" methods to the Stack.prototype.
                                                       return this[this.length-1];
                                                     }
                                             });
var s = new Stack(1,2,3,4,1);
console.log(s.peak());
s[s.length] = 7;
console.log("length:",s.length);
s.push(42);
console.log(JSON.stringify(s));
console.log("length:",s.length);

for(var i in s) console.log(s[i]);
Więc widzisz.. for in pętla jest teraz bezpieczna, ponieważ dbałeś o swój kod.
  1. pętla for in jest powolna: Hell no. Jest to zdecydowanie najszybsza Metoda iteracji, jeśli zapętlasz rzadkie tablice, które są potrzebne od czasu do czasu. Jest to jeden z najważniejszych trików wydajności, które należy znać. Zobaczmy przykład. Będziemy zapętlać po rzadkiej tablicy.

var a = [];
a[0] = "zero";
a[10000000] = "ten million";
console.time("for loop on array a:");
for(var i=0; i < a.length; i++) a[i] && console.log(a[i]);
console.timeEnd("for loop on array a:");
console.time("for in loop on array a:");
for(var i in a) a[i] && console.log(a[i]);
console.timeEnd("for in loop on array a:");
 7
Author: Redu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-28 08:16:02

Ponieważ będzie iteracją właściwości należących do obiektów w łańcuchu prototypów, jeśli nie będziesz ostrożny.

Możesz użyć for.. in, tylko pamiętaj, aby sprawdzić każdą właściwość za pomocą hasOwnProperty .

 6
Author: JAL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-23 21:20:54

Nie jest to koniecznie złe (w zależności od tego, co robisz), ale w przypadku tablic, jeśli coś zostało dodane do Array.prototype, to uzyskasz dziwne wyniki. Gdzie można się spodziewać, że ta pętla będzie działać trzy razy:

var arr = ['a','b','c'];
for (var key in arr) { ... }

Jeśli funkcja o nazwie helpfulUtilityMethod została dodana do Array ' S prototype, wtedy twoja pętla będzie działać cztery razy: key będzie 0, 1, 2, i helpfulUtilityMethod. Jeśli spodziewałeś się tylko liczb całkowitych, oops.

 5
Author: josh3736,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-23 21:25:07

Powinieneś używać for(var x in y) tylko na listach właściwości, a nie na obiektach (jak wyjaśniono powyżej).

 5
Author: user268396,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-23 21:25:10

Używanie pętli for...in dla tablicy nie jest złe, chociaż domyślam się, dlaczego ktoś ci powiedział, że:

1.) Istnieje już funkcja wyższego rzędu lub metoda, która ma taki cel dla tablicy, ale ma większą funkcjonalność i szczuplejszą składnię, zwaną 'forEach': Array.prototype.forEach(function(element, index, array) {} );

2.) Tablice zawsze mają długość, ale for...in i forEach nie wykonują funkcji dla żadnej wartości, która jest 'undefined', tylko dla indeksów, które mają zdefiniowaną wartość. Więc jeśli przypisasz tylko jedną wartość, te pętle będą tylko wykonaj funkcję raz, ale ponieważ tablica jest wyliczana, zawsze będzie miała długość do najwyższego indeksu, który ma zdefiniowaną wartość, ale ta długość może pozostać niezauważona podczas korzystania z tych pętli.

3.) Standard for loop wykona funkcję tyle razy, ile zdefiniujesz w parametrach, a ponieważ tablica jest numerowana, bardziej sensowne jest zdefiniowanie, ile razy chcesz wykonać funkcję. W przeciwieństwie do innych pętli, pętla for może następnie wykonać funkcję dla każdego indeksu w tablica, niezależnie od tego, czy wartość jest zdefiniowana, czy nie.

Zasadniczo można użyć dowolnej pętli, ale należy dokładnie pamiętać, jak one działają. Zrozum warunki, na jakich powtarzają się różne pętle, ich oddzielne funkcjonalności i zdaj sobie sprawę, że będą one mniej lub bardziej odpowiednie dla różnych scenariuszy.

Można również uznać za lepszą praktykę stosowanie metody forEach niż pętli for...in w ogóle, ponieważ jest łatwiejsza w pisaniu i ma większą funkcjonalność, więc można chcesz się w zwyczaju tylko za pomocą tej metody i standard dla, Ale telefon.

Zobacz poniżej, że dwie pierwsze pętle uruchamiają tylko konsolę.instrukcje loguj raz, podczas gdy standard dla pętli wykonuje funkcję tyle razy, ile podano, w tym przypadku array.długość = 6.

var arr = [];
arr[5] = 'F';

for (var index in arr) {
console.log(index);
console.log(arr[index]);
console.log(arr)
}
// 5
// 'F'
// => (6) [undefined x 5, 6]

arr.forEach(function(element, index, arr) {
console.log(index);
console.log(element);
console.log(arr);
});
// 5
// 'F'
// => Array (6) [undefined x 5, 6]

for (var index = 0; index < arr.length; index++) {
console.log(index);
console.log(arr[index]);
console.log(arr);
};
// 0
// undefined
// => Array (6) [undefined x 5, 6]

// 1
// undefined
// => Array (6) [undefined x 5, 6]

// 2
// undefined
// => Array (6) [undefined x 5, 6]

// 3
// undefined
// => Array (6) [undefined x 5, 6]

// 4
// undefined
// => Array (6) [undefined x 5, 6]

// 5
// 'F'
// => Array (6) [undefined x 5, 6]
 3
Author: mrmaclean89,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 12:18:48

For...in {[6] } jest przydatne podczas pracy nad obiektem w JavaScript, ale nie dla tablicy, ale nadal nie możemy powiedzieć, że jest to niewłaściwy sposób, ale nie jest to zalecane, spójrz na poniższy przykład używając for...in pętla:

let txt = "";
const person = {fname:"Alireza", lname:"Dezfoolian", age:35}; 
for (const x in person) {
    txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

OK, zróbmy to z Array Teraz:

let txt = "";
const person = ["Alireza", "Dezfoolian", 35]; 
for (const x in person) {
   txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

Jak widzisz wynik ten sam...

Ale spróbujmy czegoś, prototypujmy coś do Array...

Array.prototype.someoneelse = "someoneelse";

Teraz tworzymy nową tablicę ();

let txt = "";
const arr = new Array();
arr[0] = 'Alireza';
arr[1] = 'Dezfoolian';
arr[2] = 35;
for(x in arr) {
 txt += arr[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 someoneelse

Widzisz someoneelse !!!... W tym przypadku przechodzimy przez nowy obiekt Array!

Więc jest to jeden z powodów, dla których musimy użyć for..in ostrożnie, ale nie zawsze tak jest...

 1
Author: Alireza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-25 13:38:50

Ponieważ elementy JavaScript są zapisywane jako standardowe właściwości obiektu, to nie zaleca się iteracji za pomocą tablic JavaScript przy użyciu for...in pętli, ponieważ elementy normalne i wszystkie właściwości wyliczeniowe będą na liście.

Z https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections

 0
Author: Badr Elmers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-14 01:23:48

A for...in loop zawsze wylicza klucze. Właściwości obiektów klucze są zawsze ciągiem znaków, nawet indeksowane właściwości tablicy:

var myArray = ['a', 'b', 'c', 'd'];
var total = 0
for (elem in myArray) {
  total += elem
}
console.log(total); // 00123
 0
Author: Maher Tliba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-04 16:10:34