Сам по себе оператор for-in
не является "плохой практикой", однако он может быть неправильно использован , например, для итерации над массивами или объектами, похожими на массивы .
Цель оператора for-in
состоит в том, чтобы перечислить по свойствам объекта. Это утверждение будет развиваться в цепочке прототипов, также перечисляя более унаследованные свойства, что иногда нежелательно.
Кроме того, порядок итерации не гарантируется спецификацией, что означает, что если вы хотите «перебрать» объект массива, с этим оператором вы не можете быть уверены, что свойства (индексы массива) будут посещены в числовом заказ.
Например, в JScript (IE <= 8) порядок перечисления даже для объектов Array определяется при создании свойств: </p>
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
}
}