函数提升和变量提升

122 阅读2分钟

函数提升

函数声明时,会将声明提升到当前作用域的顶部

{
    fun()
    function fun(){
        console.log(123) // 123
    }
}

上面的代码在声明fun前就调用了fun,结果是正常执行,输出123,说明了函数声明会被提升

创建函数还有两种方式

1、通过构造函数

2、函数表达式

这两种方式使用时是将生成的函数赋值给一个变量,若该变量是用var声明的,则存在的是变量提升

函数表达式

//var 变量提升
{
    fun() // TypeError: fun is not a function
    var fun = function(){
        console.log(123)
    }
}
//let 不存在变量提升,浏览器环境下直接报变量未定义的错误
//node环境下,报错:ReferenceError: Cannot access 'fun' before initialization
//不同环境下的报错信心不一致
{
    fun() // Uncaught ReferenceError: fun is not defined
    let fun = function(){ //
        console.log(123)
    }
}

构造函数

{
    fun() // TypeError: fun is not a function
    var fun = new Function(console.log(123))
}

{
    fun() // Uncaught ReferenceError: fun is not defined
    let fun = Function(console.log(123))
}

结论:所以只有函数声明才会存在函数提升

变量提升

用var声明的变量会被提升到当前作用域的顶部

{
    console.log(a) // undefined
    var a = 123
}

函数提升和变量提升的优先级

  console.log(a) // ƒ a(){}
  var a = 123
  function a(){}

编译后:

var a
function a(){} //覆盖a变量的undefined值
console.log(a)  // ƒ a(){}
a = 123  

结论:存在同名的var变量和函数声明时,变量提升会将变量声明提升到函数声明之前,同名的函数声明会覆盖变量,所以函数声明提升的优先级要高于var的变量声明提升

console.log(b)  // ƒ b(){}
b() // 123
var b = 123
b() // TypeError: fun is not a function
function b(){
    console.log(123)
}

编译后:

//变量提升
var b
//函数声明被提升
function b(){
    console.log(123)
}
console.log(b)  // ƒ b(){}
b() // 123
b = 123 //覆盖函数声明
b() // TypeError: fun is not a function

结论:因为函数声明被提升了,在同名的var变量被赋值的时候,会覆盖函数声明,变量赋值的优先级高于函数声明

结论

1. 变量提升会将变量声明提升到函数声明之前

2. 函数提升优先级高于变量提升

3. 变量赋值优先级高于函数提升

自测环节

console.log(a)
a()
var a = 1
function a(){
    console.log(123)
}
console.log(a)
a = 2
a()