Область в примере JavaScript с конфликтующими примерами

#javascript

#javascript

Вопрос:

 var age = 23;

function foo() {
  console.log(age);
  var age = 65;
  console.log(age);
}

foo();  

Выводит:

 undefined
65
  

но

 var a = 'hello!';
first();

function first() {
  var b = 'hi!';
  second();

  function second() {
    var c = 'hey!';
    console.log(a   b   c);
  }
}  

Выводит:

 hello!hi!hey!
  

Почему в первой функции age не определено, а во второй a правильно привязано к hello! ?

Комментарии:

1. когда вы используете var в новой области видимости, это создает совершенно новую переменную. если вы хотите переопределить существующую переменную, вам нужно оставить var вне ее

Ответ №1:

Потому что, когда вы используете var и пишете это:

 function foo() {
   console.log(age);
   var age = 65;
   console.log(age);
}
  

js думает, что вы написали это:

 function foo() {
   var age; // it is undefined
   console.log(age);
   age = 65;
   console.log(age);
}
  

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

Также, как упоминалось в комментарии, вам действительно следует использовать let or const и забыть о var . var на данный момент устарел, imo.

Комментарии:

1. Правильно, также полезно указать, что такого поведения можно избежать, используя let вместо var для функциональных переменных

2. Она ведет себя по-разному из-за области видимости, вторая функция вложена внутрь первой, поэтому у нее будет доступ к переменной b , когда она регистрируется на консоли

Ответ №2:

В Javascript переменные «подняты», то есть даже те, которые вы поместили age во вторую строку в foo , на самом деле код выглядит следующим образом:

 function foo() {
  var age; // which in practice means that age = undefined
  console.log(age);
  age = 65;
  console.log(age);
}
  

Ответ №3:

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

 function foo() {
   console.log(age);
   var age = 65;
   console.log(age);
}
  

похоже на

 var age = 23;
function foo() {
   var age // age hoisted to here
   console.log(age);
   age = 65;
   console.log(age);
}
  

Это также создает проблемы с циклами и асинхронными операциями, как показано ниже:

 function foo() {
  for (var i = 0; i <= 6; i  ) {
    setTimeout(()=>console.log(i), 0)
  }
}
foo()
  

Вместо ожидаемого результата, подобного 0,1,2 .., вы получите семь из 7, и причина та же — объявление var, поднимающееся до вершины функции, нарушает область видимости цикла. Затем цикл завершает свою работу, i становится 7, и это значение попадает в обратный вызов setTimeout благодаря закрытию.
Чтобы избежать этого, вообще не используйте var — поскольку в ES6 как const, так и let являются наилучшей практикой.