Почему использование «for… in» с итерацией массива - плохая идея?

1579

Мне сказали не использовать for...in с массивами в JavaScript. Почему бы и нет?

  • 43
    Я видел недавний вопрос, где кто-то сказал вам это, но они предназначались только для массивов. Это считается плохой практикой для итерации по массивам, но не обязательно для итерации по элементам объекта.
  • 17
    Множество ответов с циклами «for», таких как «for (var i = 0; i <hColl.length; i ++) {}», сравнивают с «var i = hColl.length; тогда как (i--) {} ', который, когда возможно использовать последнюю форму, значительно быстрее. Я знаю, что это тангенциально, но думал, что добавлю это немного.
Показать ещё 11 комментариев
Теги:
arrays
for-loop
loops
iteration

25 ответов

1376
Лучший ответ

Причина в том, что одна конструкция:

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
*/

может иногда отличаться от другого:

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
*/

Также подумайте, что библиотеки JavaScript могут делать такие вещи, которые будут влиять на любой создаваемый массив:

// 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
*/
  • 134
    Исторически сложилось так, что некоторые браузеры даже перебирали «length», «toString» и т. Д.!
  • 387
    Не забудьте использовать (var x in a) вместо (x in a) - не хотите создавать глобальный.
Показать ещё 21 комментарий
359

Операция for-in сама по себе не является "плохой практикой", однако ее можно неправильно использовать, например, для итерации массивов или объектов типа массива.

Цель оператора for-in - перечислить свойства объекта. Этот оператор будет расти в цепочке прототипов, также перечисляя над унаследованными свойствами, что иногда не желательно.

Кроме того, порядок итераций не гарантируется спецификацией. Это означает, что если вы хотите "итерации" объекта массива, с этим утверждением вы не можете быть уверены, что свойства (индексы массива) будут посещаться в числовом порядок.

Например, в JScript (IE <= 8) порядок перечисления даже в объектах Array определяется как свойства были созданы:

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
}

Кроме того, говоря о унаследованных свойствах, если вы, например, расширяете объект Array.prototype (например, некоторые библиотеки как MooTools), эти свойства также будут перечислены:

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

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

Как я уже говорил, для итерации по массивам или объектам, подобным массиву, лучше всего использовать последовательный цикл, такой как простой старт for/while.

Если вы хотите перечислить только собственные свойства объекта (те, которые не наследуются), вы можете использовать метод hasOwnProperty:

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

И некоторые люди даже рекомендуют вызывать метод непосредственно из Object.prototype, чтобы избежать проблем, если кто-то добавляет свойство с именем hasOwnProperty к нашему объекту:

for (var prop in obj) {
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
    // prop is not inherited
  }
}
  • 10
    См. Также for..in Дэвида Хамфри. Итерации по объектам в JavaScript быстро - для массива for..in намного медленнее, чем «нормальные» циклы.
  • 17
    Вопрос о последнем пункте о hasOwnProperty: если кто-то переопределит hasOwnProperty объекта, у вас будут проблемы. Но не будет ли у вас таких же проблем, если кто-то переопределит «Object.prototype.hasOwnProperty»? В любом случае, они облажались, и это не ваша ответственность, верно?
Показать ещё 3 комментария
106

Существует три причины, по которым вы не должны использовать for..in для итерации по элементам массива:

  • for..in будет охватывать все собственные и унаследованные свойства объекта массива, которые не являются DontEnum; это означает, что если кто-то добавляет свойства к определенному объекту массива (есть веские причины для этого - я сделал это сам) или изменил Array.prototype (который считается плохой практикой в ​​коде, который должен хорошо работать с другими скриптами) эти свойства также будут повторяться; унаследованные свойства можно исключить, проверив hasOwnProperty(), но это не поможет вам со свойствами, установленными в самом объекте массива

  • for..in не гарантируется сохранение упорядочения элементов

  • он медленный, потому что вам нужно пройти все свойства объекта массива и его целую цепочку прототипов и все равно получить только имя свойства, т.е. получить значение, потребуется дополнительный поиск

49

Потому что для... в перечислении через объект, который содержит массив, а не сам массив. Если я добавлю функцию в цепочку прототипов массивов, это также будет включено. То есть.

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

Это будет писать:

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

И поскольку вы никогда не можете быть уверены, что в цепочку прототипов ничего не будет добавлено, просто используйте цикл for для перечисления массива:

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

Это будет писать:

0 = foo
1 = bar
  • 15
    Массивы являются объектами, нет «объекта, который содержит массив».
37

В изобилии нет ничего плохого в использовании in-in на массивах. For-in выполняет итерации над именами свойств объекта, а в случае массива "из коробки" свойства соответствуют индексам массива. (Встроенные атрибуты типа length, toString и т.д. Не включены в итерацию.)

Однако, если ваш код (или используемая структура) добавляет настраиваемые свойства к массивам или прототипу массива, то эти свойства будут включены в итерацию, которая, вероятно, не является тем, что вы хотите.

Некоторые JS-структуры, такие как Prototype, модифицируют прототип Array. Другие структуры, такие как JQuery, не работают, поэтому с JQuery вы можете безопасно использовать in-in.

Если у вас есть сомнения, вы, вероятно, не должны использовать for-in.

Альтернативный способ итерации через массив - использовать цикл for:

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

Однако это имеет другую проблему. Проблема в том, что массив JavaScript может иметь "дыры". Если вы определяете arr как:

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

Затем массив имеет два элемента, но длину 101. Использование for-in даст два индекса, тогда как for-loop даст 101 индекс, где 99 имеет значение undefined.

30

В дополнение к причинам, приведенным в других ответах, вы можете не захотеть использовать структуру "для... в", если вам нужно выполнить математику с переменной счетчика, поскольку цикл выполняет итерации по именам свойств объекта и поэтому переменная является строкой.

Например,

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

будет писать

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

тогда,

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

будет писать

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

Конечно, это легко преодолеть, включив

ii = parseInt(ii);

в цикле, но первая структура более прямая.

  • 6
    Вы можете использовать префикс + вместо parseInt если вам действительно не нужно целое число или игнорировать недопустимые символы.
  • 0
    Кроме того, использование parseInt() не рекомендуется. Попробуйте parseInt("025"); и это не удастся.
Показать ещё 1 комментарий
27

Начиная с 2016 года (ES6) мы можем использовать for…of для итерации массива, как уже заметил Джон Слегерс.

Я просто хотел бы добавить этот простой демонстрационный код, чтобы сделать все более ясным:

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++;
    }

Консоль показывает:

for...of:

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

for...in:

0: 5
1: foo

Другими словами:

  • for...of подсчитывается от 0 до 5, а также игнорирует Array.prototype.foo. Он показывает значения массива .

  • for...in перечисляет только 5, игнорируя индексы массива undefined, но добавляя foo. Он показывает имена свойств массива .

21

Короткий ответ: это просто не стоит.


Более длинный ответ: это просто не стоит, даже если порядок последовательных элементов и оптимальная производительность не требуются.


Длинный ответ: это просто не стоит, по следующим причинам:

  • Использование for (var i in array) {} приведет к тому, что 'array' будет интерпретироваться как любой другой чистый объект, пройдя цепочку свойств объекта и, в конечном счете, выполняя медленнее, чем цикл for на основе индексов.
  • Не гарантируется возврат свойств объекта в последовательном порядке, как можно было бы ожидать.
  • Использование hasOwnProperty() или isNaN() проверок для фильтрации свойств объекта - дополнительные накладные расходы, заставляющие его выполнять (даже больше) медленнее. Кроме того, введение такой дополнительной логики отрицает основную причину ее использования в первую очередь, то есть из-за более сжатого формата.

По этим причинам приемлемый компромисс между производительностью и удобством даже не существует. Действительно, нет никакой выгоды, если только намерение заключается в том, чтобы рассматривать массив как чистый объект и выполняет операции над свойствами объекта массива.

20

Помимо того, что for... in перебирает все перечислимые свойства (это не то же самое, что "все элементы массива"!), см. http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf, раздел 12.6.4 (пятое издание) или 13.7.5.15 (7-е издание):

Механика и порядок перечисления свойств... не указывается...

(Подчеркните мой.)

Это означает, что если браузер хотел, он мог бы пройти через свойства в том порядке, в котором они были вставлены. Или в численном порядке. Или в лексическом порядке (где "30" доходит до "4"! Помните о всех объектных ключах - и, следовательно, все индексы массива - фактически являются строками, поэтому это имеет смысл). Он может проходить через них ведро, если он реализует объекты как хеш-таблицы. Или возьмите любое из этого и добавьте "назад". Браузер может даже итерировать случайно и быть совместимым с ECMA-262, если он посетил каждое свойство ровно один раз.

На практике большинство браузеров в настоящее время любят итератировать примерно в том же порядке. Но ничего не говорится, что нужно. Эта реализация специфична и может измениться в любое время, если другой способ окажется более эффективным.

В любом случае for... in не несет никакой коннотации порядка. Если вы заботитесь о порядке, будьте откровенны и используйте обычный цикл for с индексом.

15

В основном две причины:

One

Как и другие, вы можете получить ключи, которые не находятся в вашем массиве или унаследованы от прототипа. Итак, если, скажем, библиотека добавляет свойство к прототипам Array или Object:

Array.prototype.someProperty = true

Вы получите его как часть каждого массива:

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

вы можете решить это с помощью метода hasOwnProperty:

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

но это верно для итерации по любому объекту с циклом for-in.

Два

Обычно порядок элементов в массиве важен, но цикл for-in не обязательно будет итерации в правильном порядке, потому что он рассматривает массив как объект, который реализуется в JS, а не как массив. Это похоже на небольшую вещь, но это может действительно испортить приложения и трудно отлаживать.

  • 2
    Object.keys(a).forEach( function(item) { console.log(item) } ) перебирает массив собственных ключей свойств, а не тех, которые унаследованы от прототипа.
  • 2
    Правда, но, как и в цикле for-in, он не обязательно будет в правильном порядке индекса. Кроме того, он не будет работать на старых браузерах, не поддерживающих ES5.
Показать ещё 3 комментария
15

Потому что он перечисляет через поля объекта, а не индексы. Вы можете получить значение с индексом "длина", и я сомневаюсь, что вы этого хотите.

  • 0
    Так каков лучший способ сделать это?
  • 3
    for (var i = 0; i <arr.length; i ++) {}
Показать ещё 3 комментария
14

Проблема с for ... in ... — и это становится проблемой, когда программист действительно не понимает язык; это не ошибка или что-то еще; заключается в том, что он выполняет итерацию по всем элементам объекта (ну, все перечисляемые члены, но эта деталь на данный момент). Если вы хотите перебирать только индексированные свойства массива, единственным гарантированным способом сохранения семантически согласованных значений является использование целочисленного индекса (т.е. Цикла стиля for (var i = 0; i < array.length; ++i)).

Любой объект может иметь связанные с ним произвольные свойства. Не было бы ничего страшного в загрузке дополнительных свойств в экземпляр массива, в частности. Код, который хочет видеть только индексированные свойства, подобные массиву, поэтому должен придерживаться целочисленного индекса. Код, который полностью знает, что for ... in действительно и действительно должен видеть все свойства, ну, тогда это тоже нормально.

  • 0
    Хорошее объяснение Пойнти. Просто любопытно. Если бы у меня был массив, который находился внутри объекта со свойствами умножения и выполнял for in , по сравнению с обычным циклом for, эти массивы перебирались бы? (что по сути, медленная производительность, верно?)
  • 2
    @NiCkNewman также объект вы ссылаетесь после in в for ... in цикле будет просто
Показать ещё 3 комментария
10

Я не думаю, что мне есть что добавить. Ответ на триптих или ответ CMS о том, почему в некоторых случаях следует избегать использования for-in.

Однако я бы хотел добавить, что в современных браузерах есть альтернатива for-in, которая может использоваться в тех случаях, когда for-in не может использоваться. Эта альтернатива for-of:

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

Примечание:

К сожалению, ни одна версия Internet Explorer не поддерживает эту функцию (Edge 12+), поэтому вам придется подождать немного дольше пока вы не сможете использовать его в своем производственном коде на стороне клиента. Тем не менее, это должно быть безопасно использовать в JS-коде на стороне сервера (если вы используете Node.js).

  • 0
    Примечание: for-in - это оператор ES6 (AKA ECMAScript 2015), который выполняет итерации по данным, которые итерируемые объекты определяют для итерации. Оператор for...in перебирает перечисляемые свойства объекта в произвольном порядке.
8

Кроме того, из-за семантики путь for, in обрабатывает массивы (то есть, как и любой другой объект JavaScript) не выравнивается с другими популярными языками.

// 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"
7

TL & DR: Использование цикла for in в массивах не является злом, на самом деле все наоборот.

Я думаю, что цикл for in является жемчужиной JS, если он правильно используется в массивах. Вы должны иметь полный контроль над своим программным обеспечением и знать, что делаете. Посмотрите на упомянутые недостатки и опровергните их один за другим.

  • Он также проходит через унаследованные свойства: Прежде всего, любые расширения для Array.prototype должны были быть выполнены с помощью Object.defineProperty(), а их дескриптор enumerable должен быть установлен на false. Любая библиотека, которая не делает этого, не должна использоваться вообще.
  • Свойства, которые вы добавляете в цепочку наследования, затем подсчитываются: При выполнении подкласса массива на Object.setPrototypeOf или по классу extend. Вы должны снова использовать Object.defineProperty(), который по умолчанию устанавливает дескрипторы свойств writable, enumerable и configurable на false. Давайте посмотрим здесь пример подкласса массива...

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]);

Итак, вы видите, что цикл for in теперь безопасен, так как вы заботитесь о своем коде.

  1. Цикл for in медленный: Ад. Это, безусловно, самый быстрый метод итерации, если вы перебираете разреженные массивы, которые требуются время от времени. Это один из самых важных трюков, которые нужно знать. Давайте посмотрим пример. Мы будем перебирать разреженный массив.

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:");
  • 0
    Можете ли вы объяснить это, пожалуйста, jsben.ch/#/BQhED
  • 0
    @Ravi Shanker Reddy Хороший бенчмаркинг настроен. Как я уже упоминал в своем ответе, цикл for in затмевает другие «если», то массив редок, и чем больше, тем больше его размер. Поэтому я переставил стендовый тест для разреженного массива arr , размером ~ 10000, только с 50 случайно выбранными элементами из [42,"test",{t:1},null, void 0] со случайными индексами. Вы сразу заметите разницу. - >> Проверьте это здесь << - .
Показать ещё 1 комментарий
7

Важным аспектом является то, что for...in выполняет только итерации над свойствами, содержащимися в объекте, которые имеют атрибут свойства перечисляемый, установленный в true. Поэтому, если вы пытаетесь выполнить итерацию объекта с помощью for...in, тогда любые свойства могут быть пропущены, если их атрибут enumerable property равен false. Вполне возможно изменить атрибут enumerable property для обычных объектов Array, чтобы определенные элементы не были перечислены. Хотя, как правило, атрибуты свойств имеют тенденцию относиться к свойствам функции внутри объекта.

Можно проверить значение атрибута свойства enumerable свойства:

myobject.propertyIsEnumerable('myproperty')

Или получить все четыре атрибута свойства:

Object.getOwnPropertyDescriptor(myobject,'myproperty')

Это функция, доступная в ECMAScript 5 - в более ранних версиях было невозможно изменить значение атрибута enumerable property (он всегда был равен true).

7

В дополнение к другим проблемам синтаксис "for..in", вероятно, медленнее, потому что индекс - это строка, а не целое число.

var a = ["a"]
for (var i in a)
    alert(typeof i)  // 'string'
for (var i = 0; i < a.length; i++)
    alert(typeof i)  // 'number'
  • 0
    Вероятно, не имеет большого значения. Элементы Array - это свойства объекта на основе Array или Array, а все свойства объекта имеют строковые ключи. Если ваш движок JS каким-то образом не оптимизирует его, даже если вы используете число, оно в конечном итоге превратится в строку для поиска.
  • 0
    Независимо от каких-либо проблем с производительностью, если вы новичок в JavaScript, используйте var i in a и ожидайте, что индекс будет целочисленным, тогда выполнение чего-то вроде a[i+offset] = <value> будет помещать значения в совершенно неправильные места , («1» + 1 == «11»).
7

for/in работает с двумя типами переменных: hashtables (ассоциативные массивы) и массив (неассоциативный).

JavaScript автоматически определит способ его прохождения через элементы. Поэтому, если вы знаете, что ваш массив действительно неассоциативный, вы можете использовать for (var i=0; i<=arrayLen; i++) и пропустить итерацию автоматического обнаружения.

Но, на мой взгляд, лучше использовать for/in, процесс, необходимый для этого автоматического обнаружения, очень мал.

Реальный ответ для этого будет зависеть от того, как браузер анализирует/интерпретирует код JavaScript. Он может меняться между браузерами.

Я не могу думать о других целях: не использовать 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]);
  • 0
    истина, если только вы не используете объекты-прототипы. ;) ниже
  • 0
    Это потому, что Array тоже Object
Показать ещё 1 комментарий
6

Потому что он будет перебирать свойства, принадлежащие объектам, в цепочке прототипов, если вы не будете осторожны.

Вы можете использовать for.. in, просто обязательно проверьте каждое свойство с помощью hasOwnProperty.

  • 2
    Недостаточно - вполне нормально добавлять произвольные именованные свойства в экземпляры массива, и они проверят true из hasOwnProperty() .
  • 0
    Хороший вопрос, спасибо. Я никогда не был настолько глуп, чтобы делать это самому массиву, поэтому я не учел это!
Показать ещё 3 комментария
5

Вы должны использовать for(var x in y) только в списках свойств, а не на объектах (как описано выше).

  • 13
    Просто примечание о SO - «выше» нет, потому что комментарии постоянно меняют порядок на странице. Итак, мы не знаем, какой комментарий вы имеете в виду. По этой причине хорошо бы сказать «в комментарии х человека».
  • 0
    @JAL ... или добавьте постоянную ссылку к ответу.
5

Это не обязательно плохо (на основе того, что вы делаете), но в случае массивов, если что-то добавлено в Array.prototype, тогда вы получите странные результаты. Где вы ожидаете, что этот цикл будет выполняться три раза:

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

Если в Array prototype добавлена ​​функция с именем helpfulUtilityMethod, тогда ваш цикл будет работать четыре раза: key будет 0, 1, 2 и helpfulUtilityMethod. Если вы ожидали только целых чисел, oops.

3

Использование цикла for...in для массива не является неправильным, хотя я могу догадаться, почему кто-то сказал вам, что:

1.) Существует уже функция или метод более высокого порядка, который имеет эту цель для массива, но имеет больше функциональности и более компактный синтаксис, называемый "forEach": Array.prototype.forEach(function(element, index, array) {} );

2.) Массивы всегда имеют длину, но for...in и forEach не выполняют функцию для любого значения 'undefined', только для индексов, которые имеют определенное значение. Поэтому, если вы назначаете только одно значение, эти циклы будут выполнять только один раз один раз, но поскольку перечисляется массив, он всегда будет иметь длину до наивысшего индекса, имеющего определенное значение, но эта длина может остаться незамеченной при использовании этих петли.

3.) Стандарт для цикла будет выполнять функцию столько раз, сколько вы определяете в параметрах, и поскольку массив пронумерован, имеет смысл определить, сколько раз вы хотите выполнить функцию. В отличие от других циклов, цикл for может затем выполнять функцию для каждого индекса в массиве, независимо от того, определено это значение или нет.

В сущности, вы можете использовать любой цикл, но вы должны точно помнить, как они работают. Понимать условия, на которых повторяются разные циклы, их отдельные функции и понимать, что они будут более или менее подходящими для разных сценариев.

Кроме того, лучше всего использовать метод forEach, чем цикл for...in в целом, поскольку его легче писать и имеет больше функциональных возможностей, поэтому вы можете захотеть привыкнуть только к используя этот метод и стандарт для, но ваш вызов.

См. ниже, что первые две петли выполняют только операторы console.log один раз, в то время как стандарт for loop выполняет функцию столько раз, сколько указано, в этом случае array.length = 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]
1

A for... in loop всегда перечисляет ключи. Ключами свойств объектов всегда являются String, даже индексированные свойства массива:

var myArray = ['a', 'b', 'c', 'd'];
var total = 0
for (elem in myArray) {
  total += elem
}
console.log(total); // 00123
  • 0
    это проблема у меня была ... большое спасибо
1

для... в полезен при работе над объектом в JavaScript, но не для массива, но мы не можем сказать это неправильно, но это не рекомендуется, посмотрите на это пример ниже, используя цикл для... в:

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

ОК, сделайте это с помощью Массив:

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

Как вы видите результат тот же самый...

Но попробуй что-нибудь, пусть прототип чего-то Массив...

Array.prototype.someoneelse = "someoneelse";

Теперь мы создаем новый массив Array();

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

Вы видите someelse!!!... Мы в этом случае перебираем новый объект Array!

Итак, одна из причин, по которой нам нужно использовать для... внутри, но это не всегда так...

0

Так как элементы JavaScript сохраняются как стандартные свойства объекта, это не рекомендуется выполнять итерацию с помощью массивов JavaScript, используя для... в поскольку обычные элементы и все перечислимые свойства будут в списке.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню