Почему переменная, определенная как глобальная, не определена?

У меня здесь простая функция и глобальная переменная.

Почему myname undefined, а не строка "global"?

var myname = "global"; // global variable
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();

Невозможно сослаться на внешнюю переменную, которая определена вне области действия этой функции? И в этом глобальная переменная...

И как я могу это исправить, чтобы я не получал undefined из глобальной переменной?


person J Rod    schedule 26.05.2015    source источник
comment
Я думаю, вы забыли 'var' в глобальной переменной   -  person crc442    schedule 27.05.2015
comment
Я считаю, что @crc442 верен. Можете ли вы опубликовать свое сообщение об ошибке для подтверждения?   -  person mas4    schedule 27.05.2015
comment
@crc442 - я полагаю, ты не понимаешь, о чем говоришь   -  person Scott Selby    schedule 27.05.2015
comment
var не нужен, и если он опущен, он будет прикреплен к окну, создавая глобальную переменную, как и хотел OP   -  person Scott Selby    schedule 27.05.2015
comment
Переменная для глобалов необязательна, что не является хорошей практикой.   -  person Roberto    schedule 27.05.2015
comment
весь твой вопрос запутан. Я предполагаю, что glabol является глобальным, а глобальный - локальным....?   -  person Andrew    schedule 27.05.2015
comment
Ой! Я совсем забыл. Это говорил мой инстинкт отладки. Я сожалею об этом.   -  person crc442    schedule 27.05.2015


Ответы (3)


Вы только что наткнулись на «функцию» js, называемую подъемом

var myname = "global"; // global variable
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();

В этом коде, когда вы определяете func, компилятор просматривает тело функции. Он видит, что вы объявляете переменную с именем myname.

Javascript Поднимает объявления переменных и функций, перемещая объявление в начало функции.

Из-за подъема ваш код переписывается следующим образом.

var myname = "global"; // global variable
function func() {
   var myname; //declare local variable and assign it undefined
   alert(myname); // "undefined"
   myname = "local"; // assign local var myname to "local"
   alert(myname); // "local"
}
func();

Это «покрывает» глобальную переменную. Если вы хотите получить доступ к глобальной переменной в рамках функции, используйте ключевое слово this.

var myname = "global"; // global variable
function func() {
    var myname = "local";
    alert(this.myname); // "global"
    alert(myname); // "local"
}
func();

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

EDIT: для полноты картины

Если вы хотите получить доступ к глобальным переменным в любом контексте, независимо от типа функции, объявите глобальную переменную, которую по соглашению вы никогда не закрываете.

var global = this; // in global scope.
var myname = "global";
var obj = {f: function () {
    var myname = "local";
    console.log(global.myname);
}};
obj.f(); // "global"

Обратите внимание, что это находится в позиции метода, а ключевое слово this напрямую относится к объекту и, следовательно, не имеет определенного myname.

person t3dodson    schedule 26.05.2015
comment
это правильный ответ, я ошибся - person Scott Selby; 27.05.2015
comment
Спасибо за объяснение. Это имеет смысл. У меня есть один вопрос. Почему объявление было отделено от присваивания в 3-й строке функции? - person codingpuss; 15.02.2016
comment
Подъем @codingpuss не перемещается туда, где происходит задание. Он только делает копию тех переменных, которые необходимы в функции, и объявляет их вверху. - person t3dodson; 27.02.2016
comment
Если это в браузере, вы можете использовать переменную window вместо вашей переменной global. - person Solomon Ucko; 23.03.2018
comment
Ничего себе, это очень плохой языковой дизайн. Неожиданное затенение переменных без уведомления пользователя. Как кто-то может выдержать этот язык, просто выше моего понимания. - person Preza8; 31.07.2020
comment
@Preza8 JS был разработан за неделю. Я думаю, что это довольно хорошо, учитывая это. - person t3dodson; 26.11.2020
comment
@ t3dodson Я тоже это слышал, и некоторые другие источники сказали мне, что это неправда. Но это не главное. Я не считаю это уважительной причиной. JS теперь намного старше недели, у них было МНОГО времени, чтобы исправить такие вещи, которые невообразимо плохи. Другая причина, по которой это не уважительная причина, заключается в том, что, вероятно, его не должны были выпускать после всего лишь недели работы. Представьте себе автомобильного дизайнера, который говорит, что мы спроектировали его за неделю, и, учитывая это, все в порядке, что он едва запускается. - person Preza8; 26.11.2020

Внутри функции вы объявляете var myname = "local". Даже если вы делаете это в середине метода, эта переменная имеет область действия функции, поэтому она принадлежит всей функции, даже коду над ней.

Таким образом, значение локальной переменной не определено до этой строки и имеет значение после, но ни одно из них не касается глобальной переменной.

person Joe Enos    schedule 26.05.2015
comment
Я не думаю, что эта часть вашего ответа точна: Таким образом, значение локальной переменной не определено перед этой строкой.... Оператор var перемещается вверх в javascript (подъем), поэтому он выполнялся перед любым другим кодом в его оценка (в данном случае функция) - person codingpuss; 15.02.2016
comment
Как новый программист, я не мог найти решение этой проблемы, сколько бы я ни читал этих ответов. Проблема в том, что я предполагал, что каждый раз, когда я хочу изменить переменную, я должен начинать строку с var (например, var myVariable = 1;, var myVariable = myVariable + 3;), тогда как на самом деле вы должны ставить var только при первой инициализации переменной. Во всех остальных случаях после этого вам нужно просто начинать строку с имени переменной и отбрасывать var (например, var myVariable = 1;, myVariable = myVariable + 3;). (иначе возникают такие вопросы, как этот вопрос) - person gamingexpert13; 31.03.2021

Причина, по которой первое предупреждение не определено, заключается в том, что вы повторно объявили global как локальную переменную под ним в функции. А в javascript это означает, что в верхней части функции она считается локальной переменной.

Тот, что ниже, работает, потому что прямо над предупреждением вы дали ему значение.

person Andrew    schedule 26.05.2015