Почему меняется значение из вызывающего кода в вызываемом?

187
11 мая 2017, 12:46

Имею следующий код:

$(document).ready(function() {
   ...
    function funcA(items) {
        // Ранее этого места index нигде не фигурирует.
        for (index = 0; index < items.length; index++) {
            var a = funcB(items[index]);
            ...
        }
    }
}
function funcB(id) {
    for (index = 0; index < initJson.length; index++) {
        item = initJson[index];
        if (item.id == id) {
            return item;
        }
    }
    return -1;
}

В функции funcA и функции funcB я использую переменные в цикле с одним и тем же именем (index), которые на первый взгляд вообще никак не связаны между собой, так как должны существовать в разны «пространствах видимости». Используя отладчик я вижу, что значение переменной index в функции funcA, после вызова funcB становится равным последнему значению в функции funcB. Подскажите, почему я наблюдаю подобное поведение? Поведение не возникает, если в цикле я объявляю переменную как var index = 0, все же, не понятно, каким образом и почему переменная из области видимости вызывающего кода попадает и изменятся в вызываемом.

Answer 1

Область видимости создают функции и модули (как IIFE через тэг script (загруженный ли код или который внутри)) и ES6 модули.
Относительно новый стандарт услышал слёзы разрабов и ввёл блочную видимость ({}) через let, const.

Объявление через var пишут переменную в ближайшую внешнюю область.
Объявления без var пишут в window (неизвестно чем руководствовались создатели, но, видимо, забористая дурь была). Это явление вырезается ошибкой в строгом режиме.

let и т. п. ограничиваются ближайшим внешним блоком.

Зная это, можно понять что в Вашем коде используется одна и та же переменная.
Допиши любой доступный модификатор видимости и всё заработало бы:

function a(){ 
  // Без указания видимости, в window 
  b = 41; 
} 
a(); 
console.info(b, window.b === b); // 41, true 
 
function a(){ 
  // В видимость функции 
  var b = 42; 
} 
a(); 
console.info(b); // ReferenceError: b is not defined

Блочная видимость:

function a(){ 
  let b = 42; 
  { 
    let b = 41; 
  } 
  console.info(b); // 42 
} 
a();

Answer 2

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

Здесь неплохо описана область видимости

READ ALSO
Как сделать exe из кода на javascript?

Как сделать exe из кода на javascript?

Написал рабочий код, для будущей программы (автопостер на доски), юзаю его через редактор js от мозилыХочу сделать программу для пк (

304