JS 变量提升和函数提升

一、提升

什么是提升?

引擎会在解释 JavaScript 代码之前进行编译,编译中的一部分工作就是找到所有的声明,并用合适的作用域将这些变量关联起来,这也是词法作用域的核心。

js 引擎会把一些变量声明和函数声明提升到对应作用域的顶层(变量针对 var 声明的)

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

// 上面等同于
var a
console.log(a)
a = 1

二、变量提升

变量声明特点

1、提升的范围是变量所处的第一层词法作用域(全局变量提升到全局顶层,函数内的变量提升到函数顶层)

2、提升的只是声明,赋值不会提升(所以一般在声明前调用是 undefined)

变量声明需要注意几个点

1、提升只针对 var 声明的变量

2、let、const 也有提升,但是存在“暂时性死区(TDZ)”

3、由于提升,所以:在全局中 var 会在 window 上面,let、const 声明的在 script

可以从下图示例中看到:

三、函数提升

函数声明特点

1、只提升函数声明,函数表达式不会提升(提升包含函数体)

2、和变量一样有对应的作用域

console.log(a)    // [Function: a]
function a(){
  console('提升')
}

// 等同于下面
function a(){
  console('提升')
}
console.log(a)



// 对于函数内部嵌套函数
console.log(b)    // [Function: b]
function b(){
  console.log(c)    // [Function: c]
  function c(){}
}
b()

// 等同于下面
function b(){
  function c(){}
  console.log(c)
}
console.log(b)
b()

四、几个示例

1、两个同时提升

console.log(a)
var a = 1

var getVarA = function () {
  console.log('调用1')
  a = 2
}

function getVarA() {
  console.log('调用2')
  a = 3
}

console.log(a)
getVarA()
console.log(a)

上面打印的结果是:undefined     1     调用1  2

上面可以等同于下面的代码

// 变量 a 的声明提升
var a

// 函数声明提升(整个提升)
function getVarA() {
  console.log('调用2')
  a = 3
}

console.log(a)
a = 1

// 函数表达式(同名函数,覆盖前面的函数体)
var getVarA = function () {
  console.log('调用1')
  a = 2
}

console.log(a)
getVarA()
console.log(a)

2、函数嵌套

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

上面输出是:10

可以对应下面的代码:

var a = 1
function foo() {
    // 不管能不能执行到,也会提升 
    var a = function(){}
    // 变量覆盖
    a = 10
    console.log(a)
    return
}
foo()
原文地址:https://www.cnblogs.com/zhurong/p/14803416.html