Объявление 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
- фактически второй оператор, а не первый).