"Var" або немає "var" в циклі "for-in" JavaScript?


99

Який правильний спосіб написання for-inциклу в JavaScript? Браузер не подає скарги ні на один із двох підходів, які я показую тут. По-перше, існує такий підхід, де ітераційна змінна xчітко оголошена:

for (var x in set) {
    ...
}

І, як альтернатива, такий підхід, який читається більш природно, але не здається мені правильним:

for (x in set) {
    ...
}

Просто наткнувся на цей пост при усуненні неполадок , чому WebPack генеруватися розшаруванням файлу призводить до виникнення помилок при для циклу , де varне використовувалися , щоб оголосити итератор i: Uncaught ReferenceError: i is not defined. Так що я буду використовувати його тепер: / WebPack лікує «глобальні» змінні Моторошно, докладніше див: stackoverflow.com/a/40416826
user1063287

Відповіді:


103

Використовуючи var, це зменшує сферу дії змінної, інакше змінна шукає до найближчого закриття в пошуку varзаяви. Якщо він не може знайти a, varто він є глобальним (якщо ви перебуваєте в суворому режимі using strict, глобальні змінні видають помилку). Це може призвести до подібних проблем.

function f (){
    for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2

Якщо ви пишете var iв циклі for для циклу, з’являється попередження 2.

Оцінка та піднімання JavaScript


4
Не відповідає на питання, це нормально для циклу, а не для.
IllidanS4 хоче, щоб Моніка повернулася

Чи не причина i == 5 обумовлена ​​більше підйомом, ніж відсутністю var у циклі for?
Снексе

1
Інший аспект importnat до цього полягає в тому, що суворий режим забороняє неявне створення властивостей gobal, тому використання стандартного циклу "for in" без вар-оператора фактично виходить з ладу і повертає ReferenceError.
dkugappi

2
Але, виходячи з Java, введення varвсередину forголови виглядає так, що це місце в циклі for, а це не так. Отже, я віддаю перевагу стилю user422039 нижче.
njlarsson

2
Що робити, якщо у вас є більше одного циклу в одній області? Вам або доведеться повторно використовувати індекс (без var), або вам доведеться оголосити багато і багато нових змінних (j, k, l, m, ...), які ви ніколи більше не будете використовувати.
армін

40

Перша версія:

for (var x in set) {
    ...
}

оголошує локальну змінну, яку називають x. Друга версія:

for (x in set) {
    ...
}

не.

Якщо xце вже локальна змінна (тобто у вас є var x;чи var x = ...;десь раніше у вашому поточному діапазоні (тобто поточна функція)), вони будуть еквівалентними. Якщо xвже не є локальною змінною, то за допомогою другої неявно буде оголошено глобальну змінну x. Розглянемо цей код:

var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
    for (x in obj1) alert(x);
}
function loop2() {
    for (x in obj2) {
        loop1(); 
        alert(x);
    }
}
loop2();

Ви могли б очікувати , що це попередження hey, there, heli, hey, there, copter, але так як xце один і той же вона буде попереджати hey, there, there, hey, there, there. Ти цього не хочеш! Використовуйте var xв forпетельках.

На завершення все: якщо forцикл знаходиться в глобальній області (тобто не у функції), то локальна область (область x, декларована в разі використання var x), така сама, як і глобальна область (область xнеявно задекларована в якщо ви використовуєте xбез var), то дві версії будуть однаковими.


3
Нарешті повна відповідь із поясненням та приємним прикладом. І це дійсно відповідає на питання.
IllidanS4 хоче, щоб Моніка повернулася

22

Ви дійсно повинні оголошувати локальні змінні var, завжди .

Ви також не повинні використовувати петлі "for ... in", якщо ви абсолютно не впевнені, що це ви хочете зробити. Для ітерації через реальні масиви (що досить часто) завжди слід використовувати цикл з числовим індексом:

for (var i = 0; i < array.length; ++i) {
  var element = array[i];
  // ...
}

Ітерація через звичайний масив з "за ... в" може мати несподівані наслідки, тому що ваш цикл може вибирати атрибути масиву, окрім числово індексованих.

редагувати - тут у 2015 році також чудово використовувати .forEach()для повторення масиву:

array.forEach(function(arrayElement, index, array) {
  // first parameter is an element of the array
  // second parameter is the index of the element in the array
  // third parameter is the array itself
  ...
});

.forEach()Метод присутній в масиві прототипу з IE9 вперед.


12

Насправді, якщо ви не любите декларацію в forзаголовку, ви можете зробити:

var x;
for (x in set) {
    ...
}

Як вже згадувалося в інших відповідях на це запитання, використання їх varзовсім не призводить до непотрібних побічних ефектів, таких як присвоєння глобальної властивості.


9

Використовуйте той, де ви оголошуєте змінну циклу var. Неявно задекларовані змінні мають різну область застосування, що, мабуть, не те, що ви задумали.


9
for(var i = 0; ...)

є загальноприйнятою схемою, але вона відрізняється від

for(int i; ...)

в C ++ тим, що змінна не охоплюється forблоком. Насправді, varпідйомники піднімаються на верхню область вкладеної області (функції), тому локальна система iбуде ефективно доступною і передfor циклом (після початку поточного сфери / функції), так і після нього.

Іншими словами, роблячи:

(function(){ //beginning of your current scope;
 //...
 for(var i in obj) { ... };
})();

те саме, що:

(function(){ //beginning of your current scope;
 var i;
 //...
 for(i in obj) { ... };
})();

ES6 має letключове слово (замість var), щоб обмежити область застосування для блоку.

Звичайно, ви повинні використовувати локальні змінні (заявлені з varабо letабо const(у ES6)), а не неявні глобали.

for(i=0; ...)або for(i in ...)вийде з ладу, якщо ви використовуєте "use strict";(як слід) і iне буде оголошено.


6

Використання var- це найчистіший спосіб, але обидва працюють так, як описано тут: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in

В основному, використовуючи, varви забезпечуєте створення нової змінної. В іншому випадку ви можете випадково використовувати раніше визначену змінну.


4

Я вважаю, що вар добре з міркувань продуктивності.

Javascript не роздивиться всю глобальну область, щоб побачити, чи існує вже десь деінде.


3

З загальної точки зору, перша версія буде призначена для індексу, який повинен знаходитись у межах циклу, а інша - будь-яка змінна в області, куди викликається конструктор циклу.

Якщо ви збираєтеся використовувати індекс циклу всередині для циклу, і це не буде потрібно для інших у наступних рядках, краще оголосіть змінну "var", тому ви будете впевнені, що "x" - це індекс циклу, ініціалізований з 0, в той час як інша, якщо в цьому контексті доступна інша зміна "х", вона буде перезаписана індексом циклу - ось у вас виникнуть деякі логічні помилки -.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.