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()