Подъем происходит в каждом контексте выполнения. Во время подъема объявления переменных или функций не перемещаются наверх, они просто записываются в память.
Когда вы запускаете файл javascript, создается первый глобальный контекст выполнения. Глобальный контекст выполнения дает глобальный объект, ключевое слово this и поднимает объявления var и объявления функций.
в первой части вашего вопроса:
var boo = 11
console.log(boo) // 11
var boo = 10
boo поднимается следующим образом:
var boo=undefined.
Потому что переменные ЧАСТИЧНО поднимаются. var boo=10
не будет перезаписывать var boo=undefined
. вот как это выглядит после подъема:
var boo=undefined
boo = 11
console.log(boo) // it is clear why 11
var boo = 10
во второй части вашего вопроса:
var boo = 11
function foo() {
console.log(boo)
var boo = 10
}
foo()
var boo в глобальном контексте частично поднят.
var boo=undefined
, но к нам это не имеет отношения. Потому что, когда мы создаем новую функцию и вызываем ее, создается новый контекст выполнения, и внутри этого контекста выполнения происходит еще один подъем следующим образом:
function foo() {
var boo=undefined
// "boo" is partially hoisted inside
// "boo" is written into the variable environment of the execution context
// "foo()" will always look into the its variable environment first
console.log(boo)
boo = 10
}
мы определили переменную более одного раза, но в разных областях. у нас есть var boo =11
в родительской области и var boo=10
в локальной области. это пример переменного затенения. foo () сначала будет использовать локальную переменную, поэтому локальная переменная затеняет родительское значение.