变量提升和函数提升
AprilTong 7/6/2021 Javascript
# js 执行
- 词法分析阶段:包括分析形参、分析变量声明、分析函数声明三个部分。通过词法分析将我们写的 js 代码转成可以执行的代码。
- 执行阶段
# 变量提升
- 只有声明被提升,初始化不会被提升
- 声明会被提升到当前作用域的顶端
🌰 1:
console.log(num)
var num
num = 6
1
2
3
2
3
预编译之后
var num
console.log(num) // undefined
num = 6
1
2
3
2
3
🌰 2:
num = 6
console.log(num)
var num
1
2
3
2
3
预编译之后
var num
num = 6
console.log(num) // 6
1
2
3
2
3
🌰 3:
function bar() {
if (!foo) {
var foo = 5
}
console.log(foo) // 5
}
bar()
1
2
3
4
5
6
7
2
3
4
5
6
7
预编译之后
function bar() {
var foo // if语句内的声明提升
if (!foo) {
foo = 5
}
console.log(foo)
}
bar()
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 函数提升
- 函数声明和初始化都会被提升
- 函数表达式不会被提升
🌰 1: 函数声明可被提升
console.log(square(5)) // 25
function square(n) {
return n * n
}
1
2
3
4
2
3
4
预编译之后
function square(n) {
return n * n
}
console.log(square(5))
1
2
3
4
2
3
4
🌰 2: 函数表达式不可被提升
console.log(square) // undefined
console.log(square(5)) // square is not a function
var square = function(n) {
return n * n
}
1
2
3
4
5
2
3
4
5
预编译之后
var square
console.log(square)
console.log(square(5))
square = function() {
return n * n
}
1
2
3
4
5
6
2
3
4
5
6
🌰 3:
function bar() {
foo() // 2
var foo = function() {
console.log(1)
}
foo() // 1
function foo() {
console.log(2)
}
foo() // 1
}
bar()
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
预编译之后:
function bar() {
var foo
foo = function foo() {
console.log(2)
}
foo() // 2
foo = function() {
console.log(1)
}
foo() // 1
foo() // 1
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 函数提升在变量提升之前
🌰 1:
console.log(foo) // 会打印出函数
function foo() {
console.log('foo')
}
var foo = 1
1
2
3
4
5
6
2
3
4
5
6
🌰 2:
var foo = 'hello' // hello
;(function(foo) {
console.log(foo)
var foo = foo || 'world'
console.log(foo) //hello
})(foo)
console.log(foo) // hello
1
2
3
4
5
6
7
2
3
4
5
6
7
预编译之后
var foo = 'hello'
;(function(foo) {
var foo
foo = 'hello' // 传入参数的foo值
console.log(foo) // hello
foo = foo || 'world' // foo有值为hello,所以没有赋值为world
console.log(foo) // hello
})(foo)
console.log(foo) // hello, 打印的事全局作用域下的var foo = 'hello'
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9