Это плохая практика использовать одно и то же имя переменной в нескольких циклах for?


Я просто пылеобразования некоторые JavaScript-код, используя у JSHint. В коде у меня есть два for-loops, которые используются следующим образом:

for (var i = 0; i < somevalue; i++) { ... }

поэтому оба for-loops используют var i для итерации.

теперь JSHint показывает мне ошибку для второго цикла for:"' i 'уже определен". Я не могу сказать, что это не так (потому что это очевидно), но я всегда думал, что это не будет иметь значения, поскольку var i используется только в этом конкретном месте.

это плохая практика, чтобы использовать циклы for таким образом? Должен ли я использовать другую переменную для каждого цикла for В моем коде, например

//for-loop 1
for (var i = 0; ...; i++) { ... }

//for-loop 2
for (var j = 0; ...; j++) { ... }

или это на e ошибок, которые я могу игнорировать (потому что он не ломает мой код, он все еще делает то, что он должен делать)?

JSLint кстати. останавливает проверку в первом цикле for, потому что я не определяю var i в верхней части функции (поэтому я переключился на JSHint в первую очередь). Итак, согласно примеру в этом вопросе: должен ли я использовать JSLint или JSHint JavaScript проверка? – Я должен использовать for-loops, как это в любом случае, чтобы подтвердить JSLint:

...
var i;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
...
//for-loop 2
for (i = 0; ...; i++) { ... }

Это также выглядит хорошо для меня, потому что таким образом я должен избегать ошибок в JSLint и JSHint. Но я не уверен в том, что я должен использовать другую переменную для каждого цикла for следующим образом:

...
var i, j;
...
//for-loop 1
for (i = 0; ...; i++) { ... }
//for-loop 2
for (j = 0; ...; j++) { ... }

Итак, есть ли лучшая практика для этого или я могу просто пойти с любым из приведенных выше кодов, что означает, что я выбираю "свою" лучшую практику?

6 56

6 ответов:

начиная с объявления переменных поднимаются в верхнюю часть области, в которой они появляются переводчика будет эффективно интерпретировать обе версии одинаково. По этой причине JSHint и JSLint предлагают переместить объявления из инициализатора цикла.

следующий код...

for (var i = 0; i < 10; i++) {}
for (var i = 5; i < 15; i++) {}

... эффективно интерпретируется следующим образом:

var i;
for (i = 0; i < 10; i++) {}
for (i = 5; i < 15; i++) {}

обратите внимание, что на самом деле есть только одно объявление i, и несколько заданий к нему - вы не может действительно "переопределить" переменную в той же области.

на самом деле ответить на ваш вопрос...

есть ли лучшая практика для этого или я могу просто пойти с любым из кодов, указанных выше?

существуют различные мнения о том, как лучше справиться с этим. Лично я согласен с JSLint и думаю, что код яснее, когда вы объявляете все переменные вместе в верхней части каждой области. Поскольку именно так будет интерпретироваться код, почему бы не написать код что выглядит как он себя ведет?

но, как вы заметили, код будет работать независимо от принятого подхода, поэтому это выбор стиля/соглашения, и вы можете использовать любую форму, с которой вам наиболее комфортно.

переменные в javascript являются областью действия (а не областью блока).

при определении var i в цикле он остается там в цикле, а также в функции, имеющей этот цикл.

см. ниже

function myfun() {
    //for-loop 1
    for (var i = 0; ...; i++) { ... }

    // i is already defined, its scope is visible outside of the loop1.
    // so you should do something like this in second loop.

    for (i = 0; ...; j++) { ... }

    // But doing such will be inappropriate, as you will need to remember
    // if `i` has been defined already or not. If not, the `i` would be global variable.
}

Я знаю, что на этот вопрос был дан ответ, но если вы хотите супер для циклов, напишите их так:

var names = ['alex','john','paul','nemo'],
    name = '',
    idx = 0,
    len = names.length;

for(;idx<len;++idx)
{
    name = names[idx];
    // do processing...
}

здесь происходит несколько вещей...

  1. длина массива хранится в len. Это останавливает JS оценки шаг

  2. The idx инкремент является предварительным инкрементом (например, ++idx не idx++). Предварительные приращения изначально быстрее, чем пост-приращения.

  3. в хранение ссылки на name. Это необязательно, но рекомендуется, если вы будете использовать name переменной большое. Каждый звонок в names[idx] требуется найти индекс в массиве. Независимо от того, является ли этот поиск линейным поиском, поиском по дереву или хэш-таблицей, поиск все еще происходит. Поэтому сохраните ссылку в другой переменной, чтобы уменьшить поиск.

наконец, это просто мои личные предпочтения, и у меня нет доказательств или каких-либо преимуществ. Однако мне всегда нравится инициализация переменных к типу, которым они будут, например name = '',.

это было упомянуто только в комментарий @TSCrowder: если ваша среда поддерживает его (Firefox, Node.js), в ES6 вы можете использовать let декларация

//for-loop 1
for (let i = 0; ...; i++) { ... }

//for-loop 2
for (let i = 0; ...; i++) { ... }

, который ограничивает область действия в пределах for-loop. Бонус: JSHint перестает жаловаться.

причина, по которой JSHint показывает ошибку, заключается в том, что в JS переменная scope является функцией, а объявления переменных поднимаются в верхнюю часть функции.

в Firefox вы можете использовать let ключевое слово для определения объема блока, но в настоящее время не поддерживается другими браузерами.

The let ключевое слово включено в спецификацию ECMAScript 6.

рекомендуется уменьшить область переменных, поэтому лучший способ объявить переменную итерации для циклов -

//for-loop 1
for (var i = 0; ...; i++) { ... }

//for-loop 2
for (var j = 0; ...; j++) { ... }

Я знаю область переменных, объявленных с помощью var но я о читабельности кода.