Почему локальная переменная убивает мою глобальную переменную?

Извините за этот вопрос, но эта проблема действительно испортила мне день.

Следующий код предупреждает 10, как и должно быть:

var globalId='10';  
function check(){  
    alert(globalId);  
}  
check();

Но следующий код предупреждает undefined:

var globalId='10';  
function check(){  
    alert(globalId); 
    var globalId; 
}  
check();

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

Это простой пример, но в моем исходном коде я сделал много вещей между началом функции, а затем долго проверял, было ли определено globalId, в противном случае определял его: if(!globalId){var globalId;} Это означало, что мое предупреждение находилось в верхней части функции сгенерировано undefined, как если бы JavaScript сначала выполнил всю функцию, просто чтобы посмотреть, могут ли быть объявлены какие-либо переменные, и если да, объявить их, и поэтому мое предупреждение указывало на «необъявленная» переменная.

Может ли кто-нибудь объяснить мне, почему это происходит, и если это правда, что JavaScript «предварительно объявляет» все переменные перед выполнением функции, даже переменные, объявленные в условиях, которые даже не выполняются?


person Per Spjuth    schedule 31.03.2011    source источник
comment
локальные переменные всегда будут иметь приоритет над глобальными. То же самое в C и большинстве других языков. В С++ вы можете выбрать глобальную переменную с помощью ::. В любом случае, одинаково называть глобальные и локальные переменные — плохая практика.   -  person phuclv    schedule 22.05.2014


Ответы (6)


В javascript вы должны знать, что есть нечто, называемое HOISTING.

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

eg:-

var globalId='10';
function check(){
alert(globalId); var globalId; }
check(); 

Изменения к -

var globalId='10';
function check(){
var globalId;
alert(globalId);}
check(); 

Поскольку globalID по-прежнему не имеет никакого значения, он возвращает значение undefined в вашем выводе. Локальные переменные всегда имеют приоритет над глобальными переменными с тем же именем.

person Sachin Shanbhag    schedule 31.03.2011
comment
Во-первых, спасибо вам и всем остальным, кто так быстро дал мне ответ о области видимости, я не знал, что все переменные перемещаются наверх перед выполнением. Но в этом есть недостаток, и если я объявлю переменную var globalId=ABC123 внутри функции, она все равно выдаст предупреждение undefined. объявление не могло быть перемещено наверх, если бы тогда мое предупреждение не было ABC123 вместо неопределенного? Как я вижу, Javascript перемещает представление о том, что globalid БУДЕТ объявлен, и поэтому к нему нельзя получить доступ до того, как это будет сделано, как это будет позже в коде...? - person Per Spjuth; 31.03.2011
comment
@per Spjuth - вверх перемещается только объявление, а не задание. Следовательно, вы все равно получите undefined, если у вас нет назначения перед предупреждением. - person Sachin Shanbhag; 31.03.2011

Да, все переменные, объявленные где-либо в функции, являются локальными для этой функции и существуют во всем коде функции; они будут использоваться вместо глобальных переменных с тем же именем.

Из https://developer.mozilla.org/en/JavaScript/Guide/Values,_Variables,_and_Literals#Variable_Scope :

JavaScript не имеет области действия блочного оператора; скорее, он будет локальным для кода, в котором находится блок. [...] Еще одна необычная вещь о переменных в JavaScript заключается в том, что вы можете ссылаться на переменную, объявленную позже, без получения исключения. Эта концепция известна как подъем; переменные в JavaScript в некотором смысле «поднимаются» или поднимаются наверх функции или инструкции.

person Gareth McCaughan    schedule 31.03.2011

Во второй части кода локальная переменная маскирует глобальную.

var globalId='10';

function check() {
    // Your are defining a local variable in this function
    // so, the global one is not visible.
    alert(globalId);
    var globalId;
}

check(); 


Тот факт, что оператор yopur var находится в конце определения функции, ничего не меняет: глобальная переменная маскируется для всей функции.

Таким образом, для всего выполнения функции переменная globalId будет ссылаться на локальную, а не на глобальную.

Однако за пределами этой функции глобальная переменная все еще будет существовать — ее просто не будет видно внутри функции из-за оператора var.

person Pascal MARTIN    schedule 31.03.2011

Как уже было сказано, в соответствии с правилами области видимости JavaScript локальная переменная маскирует глобальную для всей функции. Однако доступ к глобальной переменной возможен, попробуйте следующее.

var globalId='10';

function check() {
    // Your are defining a local variable in this function
    // so, the global one is not visible.
    alert('Local : ' + globalId + ', Global : ' + window.globalId);
    var globalId;
}

check(); 
person HBP    schedule 31.03.2011

вы объявляете НОВУЮ переменную globalId внутри области действия функции, поэтому она не определена, и это правильно. И нет, это не убивает вашу глобальную переменную, вы можете проверить это, добавив alert(globalId); после вызова check();.

person Emmerman    schedule 31.03.2011

как если бы Javascript сначала выполнил всю функцию, просто чтобы посмотреть, могут ли быть объявлены какие-либо переменные

это ответ, более или менее. Интерпретатор JavaScript ищет объявления переменных в каждой области видимости, а затем «перемещает их» в верхнюю часть области видимости.

person pawel    schedule 31.03.2011
comment
Javascript не выполняет всю функцию, он просто анализирует функцию. Объявления перемещаются наверх перед фактическим выполнением функции. - person Martijn; 31.03.2011