0

Раньше думала, что всплытие происходит на самый верх области видимости переменной. То есть как тут. Так как переменная видна только в функции, то соответственно, объявление будет происходит в самом начале функции.

var foo = 1; 
function bar() { 
  //var foo; 
  if (!foo) { 
  var foo = 10; 
} 
console.log(foo); 
} 
bar();

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

//var a; 
function c() { 
a = 7; 
} 
c(); 
console.log(a);

Почему так работает?

Eva
  • 1,889
  • 8
  • 26
  • Потому что отсутствует var – andreymal Mar 25 '21 at 22:43
  • @andreymal что вы имеете в виду? var и там, и там отсутствует. Он же потом сам добавляется при всплытии, которое вызывает объявление – Eva Mar 25 '21 at 22:45
  • В первом случае вы явно написали var в строке var foo = 10, он и всплывает в начало функции. Во втором случае никакого var нет и его никто никуда не добавляет, и поэтому создаётся глобальная переменная – andreymal Mar 25 '21 at 22:47
  • window.a либо global.a будут содержать 7. А это глобальные объекты, т.е. будут видны везде. – entithat Mar 25 '21 at 23:05

1 Answers1

2

При присваивании выполняется абстрактная операция PutValue

Как указано в спецификации в 5 пункте:

5. Если переменная не определена, то
    а. Если строгий режим
        i. Кинуть ошибку ReferenceError.
b. Получить ссылку на глобальный объект.
c. Установить в глобальном объекте свойство с именем соответствующим имени переменной и значением - соответствующим значению переменной.

Формально для браузера, код

function c() { 
  a = 7; 
} 

Эквивалентен

function c() { 
  window.a = 7; 
} 

В случае, если a нигде не объявлена.

Grundy
  • 81,538
  • То есть... правильно ли я понимаю: при hoisting'e объявление переменной всплывает на более высокий уровень вложенности? Из if выше - в саму функцию, а из функции (во втором примере) - на самый высокий уровень ( "а" становится глобальной переменной) – Eva Mar 25 '21 at 23:15
  • @Eva, нет не правильно. "всплытие" происходит всегда на том уровне где переменная объявлена. В случае var - это уровень функции, в случаях let/const - уровень блока. В случае в вопросе - "всплытия" вообще нет. – Grundy Mar 25 '21 at 23:20
  • 1
    @Eva фигурные скобки ограничивают видимость для переменных объявленных с помощью let, const, переменные объявленные с помощью var - ограничены функциями – Grundy Mar 26 '21 at 10:13
  • все, теперь понятно) спасибо! – Eva Mar 26 '21 at 10:19
  • И именно поэтому получается, что переменные объявленные с помощью let и const не всплывают, правильно? – Eva Mar 26 '21 at 10:21
  • спасибо за ссылку) то есть если по-простому, переменная не может быть использована без инициализации. С var всплывает объявление и происходит инициализация на undefined, с let и const этого не происходит, поэтому всплытие let и const вызывает ошибку, так? – Eva Mar 26 '21 at 12:16
  • 1
    @Eva, ошибку вызывает не всплытие let и const, а попытка обратиться в неинициализированной переменной :) – Grundy Mar 26 '21 at 19:42