JavaScript程序执行是自上而下执行的

1

console.log(a)
var a = 10

通过var声明的变量会变量提升到当前作用于最顶部,所以上面代码实际是

var a
console.log(a) // undefined
a = 10

2

console.log(a) // a is not defined
a = 10

没有通过var声明变量,直接a = 10赋值操作,没有变量提升,此时console.log(a)报错 a is not defined

3

console.log(a) // a is not defined
let a = 10

if (true) {
  console.log(b) // 产生块作用于,b is not defined
}
let b = 100

通过let,const声明的变量不仅不会变量提升,而且还会形成块作用域,因此报错a is not defined

4

var flag = true
if (flag) {
  var a = 10
}
console.log(a)

因为var a = 10发生变量提升,并且if语句没有作用域,所有程序都在同一个作用域window之下所以代码实际是

var flag = true
var a
if (flag) {
  a = 10
}
console.log(a)

当flag为true的时候回输出10

当flag为false的时候输出undefined

5

foo()
function foo() {
  console.log(a)
}
var a = 10

var发生变量提升,函数声明整个函数发生变量提升所以代码实际是

var a
function foo() {
  conosle.log(a) // undefined
}
foo()
a = 10

6

foo()
var foo = function() {
  console.log(a)
}
var a = 10

函数式表达式 var foo = function...会发生变量提升,所以实际为

var foo
var a
foo() // 此时foo应该为undefined,因此输出 foo is not a function
foo = function() {
  console.log(a)
}
a = 10

7

var a = 10

function foo() {
  console.log(a)
}

foo(a) // foo运行在全局作用域 输出10

function baz() {
  var a = 100
  foo() // foo运行在baz包裹的作用域,输出10,并不会输出离自己进的100
}

baz() 

在代码运行前(也就是编译阶段),作用域都已经确定好了。 foo永远在全局作用域下,不管他在哪里运行,foo都会输出全局作用域下的a

再看以下代码

function ff() {
    console.log(b) // b is not defined
}

function kk() {
    var b = 100
    ff()
}
kk()

可以看出ff中的bkk中的b没有任何关系,我们平时写代码也不会写出这样的代码,写代码时很明确这种写法不对,但是看问题的时候反而会被代入问题中,以至于做出错误的判断...值得反思呀

# 参考

从作用域到变量提升 (opens new window)