2012-04-18 3 views
10

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

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

... и это:

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

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

Если они идентичны, то почему именно Crockford/JSLint, «Нет, не так», об этом?

+2

Возможный дубликат [переменные JavaScript объявляются вне или внутри цикла?] (Http://stackoverflow.com/questions/3684923/javascript-variables-declare-outside-or-inside-loop) –

ответ

12

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

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

EDIT

Следует отметить, что с введением ES6 let, теперь вы можете использовать пусть внутри цикла для реального блока Scoped переменная more details

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

Существует также 'let', который похож на' var' тем, что он также дает локальную область, но отличается тем, что получает область блока. Он недоступен за пределами 'for' /' if'/'while' и т. Д. – 4castle

0

Это те же самые вещи.

+0

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

+0

JSLint ничего не значит. – Rob

+1

Lol это означает что-то ... может быть, не так много, но для нуба, подобного мне, это помогает установить хорошие привычки. –

7

Проблема с объявлением в заголовке цикла 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, немного запутать объявление всех переменных в верхней части функции, а не ждать до первого использования.

+0

Так что, пока вы знакомы с обработкой JS сферы, все хорошо. –

+1

Вот почему люди должны прекратить использование «var» –

+0

Спасибо за напоминание, @SartherisStormhammer. Обновлен, чтобы удовлетворить доступность 'let' на современном языке. –

1

Там нет никакой разницы, но я предпочитаю второй путь (за Crockford), поскольку он явно показывает, что переменный имеющиеся снаружи для цикла:

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

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

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

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

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

идентичен

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

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

Смежные вопросы