2016-11-23 1 views
-2

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

EDIT: проблема устранена. Обе функции показывают только до и после. И то, что я пытаюсь понять, почему это меняется.

variable = 1; 
 
local_var_dec(); 
 
global_var_global(); 
 
    
 
function local_var_dec(){ 
 
    console.log("local: "+ variable); 
 
    if(typeof variable === 'undefined'){ 
 
     var variable = 2; 
 
    } 
 
} 
 
    
 
function global_var_global(){ 
 
    console.log("global: "+ variable); 
 
    if(typeof variable === 'undefined'){ 
 
     variable = 2; 
 
    } 
 
}

+1

Почему бы не использовать 'var' и не объявить переменную заранее? –

+0

'var variable' на глобальном уровне. попробуйте вот так: – prasanth

ответ

3

Имея var variable внутри local_var_dec, вам 're shadowing глобальный с совершенно другим местным переменной. Это означает, что глобальный недоступен в пределах local_var_dec. И потому, что var переменных водрузили, он не доступен где-нибудь в local_var_dec, точно так, как если бы это выглядело так:

function local_var_dec(){ 
    var variable;      // *** 
    console.log("local: "+ variable); 
    if(typeof variable === 'undefined'){ 
     variable = 2;     // *** 
    } 
} 

Так это означает, что когда вы присваиваете ему, то вы присваиваете к местным переменная, а не глобальная; это не имеет никакого эффекта на глобальном уровне, поэтому, когда вы вызываете global_var_global позже, вы видите исходное значение глобального.

Хотя вы все еще можете получить доступ к глобальному, вы не можете получить к нему доступ в виде переменной . Неявные globals¹, такие как yours (и объявленные с var в глобальной области), являются свойствами глобального объекта и поэтому могут быть доступны через глобальный объект, доступный как window в браузерах. Таким образом, window.variable получит доступ к нему в пределах local_var_dec в браузерах. В других средах глобальный объект, определяемый средой, может быть или не быть глобальным. Например, в NodeJS есть global. Однако вы всегда можете получить ссылку на глобальный объект от в глобальной области видимости (при условии, что среда позволяет запускать код в глобальной области, например, NodeJS).

Фундаментально, однако, избежать затенения переменных, если вам нужно получить доступ к ним, так что особенность глобалов является A) Специфическая для глобалов, B) не очень хорошая идея, и C) Не доступно с новыми let и const деклараций ,

Вот фрагмент с аннотацией, что именно происходит, и показывая с помощью window.variable (хотя опять же, в идеале просто использовать другое имя):

// This creates an *implicit global* by assigning 
 
// to an undeclared identifier 
 
variable = 1; 
 
local_var_dec(); 
 
global_var_global(); 
 
    
 
function local_var_dec(){ 
 
    // This shows `undefined` because `variable` in the below is the *local* 
 
    // variable you've declared with `var`, even though the `var` hasn't 
 
    // been reached yet. `var` is *hoisted* to the top of the function. 
 
    console.log("local: "+ variable); 
 
    // This is still the local, so it's still `undefined` 
 
    if(typeof variable === 'undefined'){ 
 
     // This sets the *local* variable to 2; it has no effect at all on 
 
     // the global 
 
     var variable = 2; 
 
    } 
 
    
 
    // If you wanted, you could use `window.variable` here 
 
    console.log("window.variable = " + window.variable); 
 
} 
 
    
 
function global_var_global(){ 
 
    // Because there's no `var` in this function, this us using the global 
 
    // `variable` 
 
    console.log("global: "+ variable); 
 
    if(typeof variable === 'undefined'){ 
 
     variable = 2; 
 
    } 
 
}


¹ неявной глобальной - глобально создано без какого-либо объявления, назначая ему. Больше в моем блоге The Horror of Implicit Globals и MDN.

+0

Следует отметить, что доступ к глобальным переменным будет различным в разных контекстах - например, 'window.variable' не будет работать в узле, например, вам нужно будет получить доступ к нему с помощью' global.variable'. Yay для тонких различий в Javascript! –

+0

@SyDy: Я отметил это. Re "yay": Это потому, что это не разница в JavaScript. :-) JavaScript не определяет 'window' (или' global'). Из [spec] (http://www.ecma-international.org/ecma-262/7.0/index.html#sec-global-object): * «В дополнение к свойствам, определенным в этой спецификации, глобальный объект может имеют дополнительные свойства, определенные узлом.Это может включать свойство, значение которого является самим глобальным объектом, например, в объектной модели документа HTML свойство окна глобального объекта является самим глобальным объектом ». * Обратите внимание на« может ». –

+0

О, я это понимаю. Просто внедрение JS обязательно противоречиво, поскольку оно определяется исключительно его спецификацией и реализовано во многих разных формах. Другими словами, _mays_ JS являются кормом для легкой путаницы ... просто спросите 'this';) –

-1

Удалить var из линии 8 и добавить его в первой строке (но не требуется)

var variable = 1; //add `var` here, not needed 
 
local_var_dec(); 
 
global_var_global(); 
 
    
 
function local_var_dec(){ 
 
    console.log("local: "+ variable); 
 
    if(typeof variable === 'undefined'){ 
 
     variable = 2; //remove `var` from here 
 
    } 
 
} 
 
    
 
function global_var_global(){ 
 
    console.log("global: "+ variable); 
 
    if(typeof variable === 'undefined'){ 
 
     variable = 2; 
 
    } 
 
}

+0

Подобно @ T.J.Crowder, указанному в другом ответе: 'var' не проблема. Это вопрос «неявных глобалов» ... – gus27

+0

Я только что опубликовал короткий и рабочий ответ :-) – Dave

+2

... но вопрос в том, «почему он меняется?» - не как это исправить. – gus27

-1

Никогда не объявлять переменную переменную без «вар», если вы хотите использовать его глобально, объявляя его без «вар» вызывает проблемы. Если вы хотите использовать его локально, вы можете это сделать, но это не очень хорошая практика. Таким образом, решение добавляет var к самой первой строке кода непосредственно перед переменной. Ex:

var variable=1; 

Затем проверьте выход.

Надеется, что это помогает < Привета Shohil

+1

Отсутствие' var' не является проблемой с кодом OP. (Это * a * проблема, но не тот, о котором спрашивает OP.) * (Не мой dv) * –

0

Пожалуйста, более конкретно с вашим вопросом. Это явно Javascript, даже если вы не указали это. Какой результат вы получаете от этого скрипта? Какой тип и версия браузера вы используете?

О ваш вопрос: я ожидал бы этот консольный вывод:

local: 1 
global: 1 

Причина: условие if(typeof variable === 'undefined') будет ложным в обоих вызовах функций. Рассмотрим функцию

function local_var_dec(){ 
    console.log("local: "+ variable); 
    if(typeof variable === 'undefined'){ 
     var variable = 2; 
    } 
} 

Где var variable = 2; определяется после этот тест для переменной быть определено так variable действительно местный.

Кроме того; если вы определяете глобальную переменную без использования var, эта переменная становится фактически свойством объекта window, а не отдельной переменной Javascript. Вы могли бы также назвать его window.variable, что означает, что вы можете непреднамеренно изменить свойство window, не используя ключевое слово var.

+0

Оператор if вычисляет true в функции 'local_var_dec'. См. Отличный ответ T.J. на подъеме ниже. –

+0

* «Это, очевидно, Javascript, даже если вы не указали это». * Да, они сделали: они отметили вопрос тегом [tag: javascript], которого вполне достаточно. –

+0

* "условие if (typeof variable === 'undefined') будет ложным в обоих вызовах функций" * Нет, это не будет. В 'local_var_dec', это правда - по этой причине я объясняю в своем ответе. Вы также можете запустить фрагмент в вопросе, чтобы увидеть его. –