栗子
print() // 1
console.log(str) // 2
var str = 'hello' // 3
function print() {
// 4
console.log(str)
}
// output: undefined undefined
1. 变量提升
- js在执行的过程中,js引擎把变量和函数的声明部分提升到代码开头的行为。
2. js执行流程
变量和函数声明在代码里的位置是不会改变的,而且在编译阶段被js引擎放入内存中,js代码编译完才会进入执行阶段
- 流程:一段js代码 -> 编译阶段 -> 执行阶段
- 由图可见:js代码编译后会生成两部分内容:执行上下文和可执行代码
执行上下文
执行上下文:js执行一段代码时的运行环境
执行上下文中存在一个变量环境的对象
- 变量环境:该对象保存了变量提升的内容
2.1 编译阶段
-
1和2 不是声明操作,js引擎不做任何处理
-
3通过var声明变量,js引擎在环境变量中创建名为str的属性,并初始化为undefined
-
4是一个函数声明,js引擎会将函数定义部分存在堆heap中,并在环境变量中创建名为print的属性,并将print的值指向堆中函数的位置
Variable Environment:
str -> undefined,
print -> function() { console.log(str)}
js引擎会把声明之外的代码编译成可执行代码
print() // 1
console.log(str) // 2
str = 'hello' // 3
2.2 执行阶段
-
执行1时,js引擎开始在变量环境中寻找该函数
-
变量环境中print存在该函数的引用,所以js引擎便开始执行该函数
-
在执行过程中发现函数用了str变量,js引擎在变量环境中寻找str变量
-
此时str在环境变量中值为undefined,输出undefined
-
-
执行2时,js引擎在变量环境中查找str,此时str在变量环境中的值为undefined,输出undefined
-
3是一个赋值操作,把‘hello’赋值给str,赋值结束后变量环境改变
Variable Environment:
str -> 'hello',
print -> function() { console.log(str)}
3. 代码中存在多个相同变量和函数时怎么办
3.1 栗子
a() // 1
var a = 'hello, world' // 2
console.log(a) // 3
function a() {
// 4
console.log('inner a function 1')
}
var a = 'hello, tomorrow' // 5
console.log(a) // 6
function a() {
// 7
console.log('inner a function 2')
}
a() // 8
- 执行结果
// inner a function 2
// hello, world
// hello, tomorrow
// 报错 a is not a function
3.2 编译阶段
-
1函数调用不做处理
-
2有var声明变量,在变量环境中创建a变量并初始化为undefined
-
3函数调用不做处理
-
4js引擎发现有同名function定义的函数a,将函数定义存储到堆heap中,并在变量环境中查找是否存在a,存在则把a的值指向该函数在堆中的位置
-
5有var声明,在变量环境在查找是否存在a,存在并且a有值,不做处理
-
6函数调用不做处理
-
7js引擎发现存在同名funtion定义的函数a,把函数定义存储在堆中,并在变量环境中查找是否存在a属性,存在则把a的值指向该函数在堆中的位置
Variable Environent:
a -> function() { console.log('inner a function 2') }
3.3 执行阶段
a() // 1
a = 'hello, world' // 2
console.log(a) // 3
a = 'hello, tomorrow' // 4
console.log(a) // 5
a() // 6
-
1js引擎开始在变量环境中寻找该函数
-
变量环境中a存在该函数的引用,所以js引擎便开始执行该函数
-
输出
inner a funciton 2
-
-
2赋值操作,把‘hello,world'赋值给a,变量环境对象改变
- 变量环境:a -> 'hello, world'
-
3打印a的信息
- 输出
hello, world
- 输出
-
4赋值操作,把’hello,tomorrow‘赋值给a,变量环境对象该百年
- 变量环境:a -> 'hello, tomorrow'
-
5函数调用,但在变量环境中,a的值为'hello, tomorrow',并没有指向函数的位置,所以报错