Запутанная операция JavaScript `var` ключевое слово - PullRequest
6 голосов
/ 19 декабря 2009

Я столкнулся с очень странной (для меня) проблемой с ключевым словом var. Я сократил его до довольно минимального тестового примера и обнаружил, что он выставлен в Node.js (например, V8 и Chrome), инспекторе Safari 4 (например, Nitro) и FireBug (очевидно, SpiderMonkey). Первоначально я готовил отчет об ошибках, но, поскольку он так широко представлен, я собираюсь предположить, что совершенно не понимаю, как JavaScript должен охватывать и искать переменные.

Тестовый случай очень маленький, и на GitHub здесь: http://gist.github.com/260067. Единственная разница между первым и вторым примером - это включение ключевого слова var.

Здесь также приведен аналогичный тестовый пример, который по-разному демонстрирует ту же «проблему»: https://gist.github.com/698b977ee0de2f0ee54a

Редактировать: Чтобы больше не пытаться объяснить, как работает каскадная область действия, я хорошо с этим знаком. Моя проблема в том, что я не понимаю, почему следующий код «работает» (в том смысле, что он «1014 * s« внешний », затем« внутренний », а затем снова« внешний »):

(function(){
  var foo = 'outer';
  alert("Outer `foo`: " + foo);

  (function(){
    foo = 'inner';
    alert("Inner `foo`: " + foo);

    var foo;
  })();

  alert("Outer `foo`: " + foo);
})();

var foo; происходит в совершенно неуместном положении для переназначения foo; так почему это влияет на это назначение очень существенным образом?

Ответы [ 3 ]

14 голосов
/ 19 декабря 2009

Дело в том, что в отличие от других языков JavaScript создает все переменные в начале функции. Это означает, что код:

(function(){
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        var myVar = 5;
    }
})();

Фактически компилируется и интерпретируется как

(function(){
    var myVar;
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        myVar = 5;
    }
})();

Чтобы создать переменную и сделать ее доступной только внутри блока if или loop, вы должны использовать let, что является новой функцией JavaScript. Я не уверен, сколько браузеров реализуют его (Firefox 3.5 делает, если вы используете <script type="text/javascript;version=1.7">).

(function(){
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        let myVar = 5;
    }
})();
2 голосов
/ 19 декабря 2009

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

Редактировать: ключевое слово let работает более условно (оно объявляет переменную только для содержащего блока), но оно доступно не во всех версиях JavaScript.

1 голос
/ 19 декабря 2009

включение var означает, что присвоение {} выполняется для экспорта локальной переменной вместо экспорта глобальной переменной, что означает, что это не имеет никакого эффекта.

...