Объявление var внутри объявления Javascript для цикла

Я уверен, что прочитал дискуссию об этом, но не могу ее найти. Просто, есть ли недостатки в объявлении инкремента цикла for внутри объявления цикла? В чем разница между ними:

function foo() {
    for (var i=0; i<7; i++) {
        // code
    }
}

... и это:

function foo() {
    var i;
    for (i=0; i<7; i++) {
        // code
    }
}

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

Если они идентичны, почему Крокфорд /JSLint все, "Нет, не так", об этом?

Ответ 1

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

Часть разработчиков Javascript очень предпочитает вторую форму. Обоснование состоит в том, что, поскольку все переменные имеют область действия функции, вы должны объявить их на уровне функции, чтобы сделать время жизни явным даже для тех, кто не знаком с Javascript. Это всего лишь стиль, хотя и отнюдь не жесткое правило

ИЗМЕНИТЬ

Обратите внимание, что с введением ES6 let, теперь вы можете использовать let внутри вашего цикла для реальной переменной с ограниченным блоком подробнее

for(let i = 1; i <= 5; i++) {
   setTimeout(function(){
       console.log('Value of i : ' + i);
   },100);
}

Ответ 2

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

var i = 1;
function foo() {
   console.log(i);                     // 'undefined'
   for (var i=1; i<100; ++i) {
   }
}

Несмотря на то, что вызов console.log происходит перед объявлением локального i, он все еще находится в области видимости, потому что он находится внутри одной и той же функции. Таким образом, локальный i, которому еще не присвоено какое-либо значение, является то, что передается в log. Это может быть удивительно; это, безусловно, не очевидно для всех, кто не знаком с правилами определения Javascript.

Начиная с ECMAScript 2015, есть лучший способ объявить переменные: let. Переменные, объявленные с помощью let, являются локальными для блока, содержащего их, а не для всей функции. Таким образом, эта версия вышеприведенного кода будет печатать 1 по назначению:

let i=1; // could use var here; no practical difference at outermost scope
function foo() {
  console.log(i);               // 1
  for (let i=1; i<100; ++i) {
  }
}

Итак, лучшей практикой в ​​современном Javascript является объявление переменных с let вместо var. Однако, если вы застряли в реализации до ECMAScript 2015, немного запутать объявление всех переменных в верхней части функции, а не ждать до первого использования.

Ответ 3

Нет никакой разницы, но я предпочитаю второй способ (за Crockford), потому что он явно показывает, что переменная доступна вне цикла for:

function() {
    for(var i=0; i<7; i++) {
        // code
    }

    // i is still in scope here and has value 7
}

Ответ 4

Это то же самое.

Ответ 5

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

Это означает, что

for(var i = 0; i < 8; i++) {
    //some Code
}

совпадает с

var i = 0;
for(;i < 8;) {
    //some Code
    i++;
}

(Точка с запятой, следующая за (, должна сообщить компьютеру, что i < 8 - фактически второй оператор, а не первый).