Подтвердить что ты не робот

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

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

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

Итак, оба for-loops используют var я для итерации.

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

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

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

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

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

JSLint btw. останавливает проверку в первом цикле for, потому что я не определяю var я в верхней части функции (поэтому я переключился на 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-loop следующим образом:

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

Переменные в 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.
}

Ответ 3

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

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

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

Несколько вещей, происходящих здесь...

  • Длина массива хранится в len. Это останавливает JS, оценивая names.length каждую итерацию

  • Приращение idx является PRE-INCREMENT (например, ++ idx NOT idx ++). Предварительные инкременты происходят быстрее, чем пост-приращения.

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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

Ответ 6

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

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

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

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