变量提升和函数提升

7/6/2021 Javascript

# js 执行

  1. 词法分析阶段:包括分析形参、分析变量声明、分析函数声明三个部分。通过词法分析将我们写的 js 代码转成可以执行的代码。
  2. 执行阶段

# 变量提升

  • 只有声明被提升,初始化不会被提升
  • 声明会被提升到当前作用域的顶端

🌰 1:

console.log(num)
var num
num = 6
1
2
3

预编译之后

var num
console.log(num) // undefined
num = 6
1
2
3

🌰 2:

num = 6
console.log(num)
var num
1
2
3

预编译之后

var num
num = 6
console.log(num) // 6
1
2
3

🌰 3:

function bar() {
    if (!foo) {
        var foo = 5
    }
    console.log(foo) // 5
}
bar()
1
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

# 函数提升

  • 函数声明和初始化都会被提升
  • 函数表达式不会被提升

🌰 1: 函数声明可被提升

console.log(square(5)) // 25
function square(n) {
    return n * n
}
1
2
3
4

预编译之后

function square(n) {
    return n * n
}
console.log(square(5))
1
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

预编译之后

var square
console.log(square)
console.log(square(5))
square = function() {
    return n * n
}
1
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

预编译之后:

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

# 函数提升在变量提升之前

🌰 1:

console.log(foo) // 会打印出函数

function foo() {
    console.log('foo')
}
var foo = 1
1
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

预编译之后

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
上次更新: 7/6/2021, 4:08:33 PM