"var" или no "var" в цикле JavaScript для "in-in"?

Какой правильный способ написать цикл for-in в JavaScript? Браузер не подает жалобы ни на один из двух подходов, которые я покажу здесь. Во-первых, существует такой подход, когда явная декларация переменной итерации x:

for (var x in set) {
    ...
}

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

for (x in set) {
    ...
}

Ответ 1

Используйте var, он уменьшает область видимости переменной, иначе переменная ищет ближайшую закрытие, ищущую инструкцию var. Если он не может найти var, тогда он глобальный (если вы находитесь в строгом режиме, using strict, глобальные переменные вызывают ошибку). Это может привести к следующим проблемам.

function f (){
    for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2

Если вы пишете var i в цикле for, предупреждение показывает 2.

Обзор и продвижение JavaScript

Ответ 2

Первая версия:

for (var x in set) {
    ...
}

объявляет локальную переменную с именем x. Вторая версия:

for (x in set) {
    ...
}

нет.

Если x уже является локальной переменной (т.е. у вас есть var x; или var x = ...; где-то раньше в вашей текущей области (то есть текущая функция)), то они будут эквивалентны. Если x уже не является локальной переменной, то использование второго неявно объявит глобальную переменную x. Рассмотрим этот код:

var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
    for (x in obj1) alert(x);
}
function loop2() {
    for (x in obj2) {
        loop1(); 
        alert(x);
    }
}
loop2();

вы можете ожидать, что это сообщит hey, there, heli, hey, there, copter, но поскольку x является одним и тем же, он будет предупреждать hey, there, there, hey, there, there. Вы этого не хотите! Используйте var x в циклах for.

В довершение всего: если цикл for находится в глобальной области (то есть не в функции), то локальная область (область x объявляется, если вы используете var x), является то же, что и глобальная область действия (область x неявно объявлена, если вы используете x без var), поэтому две версии будут идентичными.

Ответ 3

Вы действительно должны объявлять локальные переменные с var, всегда.

Вы также не должны использовать циклы "for... in", если вы не уверены, что это то, что вы хотите сделать. Для итерации через реальные массивы (что довольно часто), вы всегда должны использовать цикл с числовым индексом:

for (var i = 0; i < array.length; ++i) {
  var element = array[i];
  // ...
}

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

edit — здесь в 2015 году также можно использовать .forEach() для итерации по массиву:

array.forEach(function(arrayElement, index, array) {
  // first parameter is an element of the array
  // second parameter is the index of the element in the array
  // third parameter is the array itself
  ...
});

Метод .forEach() присутствует в прототипе Array от IE9 вперед.

Ответ 4

На самом деле, если вам не нравится объявление в заголовке for, вы можете сделать:

var x;
for (x in set) {
    ...
}

Как уже упоминалось в других ответах на этот вопрос, использование var вообще не вызывает ненужных побочных эффектов, таких как присвоение глобального свойства.

Ответ 5

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

Ответ 6

Использование var является самым чистым способом, но оба работают так, как описано здесь: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in

В принципе, используя var, вы создаете новую переменную. В противном случае вы можете случайно использовать ранее определенную переменную.

Ответ 7

for(var i = 0; ...)

- часто встречающийся образец, но он отличается от

for(int i; ...)

в С++ в том, что переменная не привязана к блоку for. Фактически, var поднимается в верхнюю часть охватывающей области (функции), поэтому локальный i будет эффективно доступен как перед циклом for (после начала текущей области/функции), так и после него.

Другими словами, делая:

(function(){ //beginning of your current scope;
 //...
 for(var i in obj) { ... };
})();

совпадает с:

(function(){ //beginning of your current scope;
 var i;
 //...
 for(i in obj) { ... };
})();

ES6 имеет ключевое слово let (вместо var), чтобы ограничить область видимости для блока.

Конечно, вам следует использовать локальные переменные (объявленные с помощью var или let или const (в ES6)), а не неявные глобальные.

for(i=0; ...) или for(i in ...) не удастся, если вы используете "use strict"; (как и должно быть) и i не объявлен.

Ответ 8

Я думаю, что var хорош по соображениям производительности.

Javascript не будет просматривать всю глобальную область видимости, если x уже существует где-то еще.

Ответ 9

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

Если вы собираетесь использовать цикл loop внутри цикла for, и это не будет требоваться другими в следующих строках, лучше объявите переменную с "var", чтобы вы были уверены, что "x" для инициализации индекса цикла с 0, в то время как другой, если в этом контексте доступна другая переменная "x", это будет перезаписано индексом цикла - у вас появятся некоторые логические ошибки -.