目录
变量提升是在代码执行时,把变量和函数的声明部分提升到代码开头的行为,变量被提升后,会被默认设置为undefined
。
变量提升
当使用var
关键字声明变量时,
consolt.log(a)
var a = 1
// undefined
等价于
var a
console.log(a)
a = 1
变量a
作为全局变量时,其声明会被提升到全局作用域的顶端,而初始化和赋值不会。
在函数作用域中
function main() {
console.log(a)
var a = 1
}
main()
// undefined
函数内部变量的声明会被提升到函数作用域的顶端,等价于
function main() {
var a
console.log(a)
a = 1
}
main()
变量形式声明的函数
JavaScript中函数的声明有两种形式
function main() {
// 函数形式声明
}
var func = main() {
// 变量形式声明
}
在使用变量形式声明函数时,也会出现提升的现象。
func()
var func = function () {
console.log("Hello World!\n")
}
// TypeError: func is not a function
func1()
function func1() {
console.log("Hello World!\n")
}
// Hello World!
变量提升导致的问题
变量被覆盖
var s = "HTML"
function main() {
console.log(s);
if (0) {
var s = "CSS"
}
}
main()
// undefined
当执行到console.log(s)
时,会在执行上下文中寻找变量s
,一个在全局上下文中HTML
,另一个在函数main
的执行上下文中CSS
。
JavaScirpt会优先从当前的执行上下文(函数的执行上下文)中查找变量,由于变量提升的存在,包含了s = undefined
。
变量不被销毁
function main() {
for (var i = 0; i < 6; ++i) {
}
console.log(i)
}
main()
// 6
避开变量提升
引入let
和const
关键字
ECMAScript6已经通过引入块级作用域和
let, const
关键字避开这种设计缺陷。
console.log(a)
let a = 1
// ReferenceError: Cannot access 'a' before initialization
function main() {
let a = 1
if (1) {
let a = 2
console.log(a)
}
console.log(a)
}
main()
// 2 1
let
关键字支持块级作用域,作用块内的变量不影响外面的变量。
块级作用域
function main() {
var a = 1
let b = 2
{
let b = 3
var c = 4
let d = 5
console.log(a)
console.log(b)
console.log(d)
}
console.log(b)
console.log(c)
}
main()
// 1 3 5 2 4
在执行代码前,JavaScript会先编译并创建执行上下文
var
声明的变量,会被存到变量环境;let
声明的变量,会被存到词法环境;- 函数内部
let
声明的变量不会存到词法环境;
执行到main
函数时,变量环境中a = 1
,词法环境中b = 2
,内部的块作用域中用let
声明的变量,存到词法环境中的单独区域。
在词法环境中,维护一个栈结构,栈底是最外层变量,进入一个作用域后,把内部的变量压到栈顶,执行完后在出栈。
执行到console.log()
时,从词法环境的栈顶向下查找,如果没有找到,继续在变量环境中查找:
块作用域执行结束后,内部变量的定义出栈,继续向下执行其余代码。
标签:console,log,JavaScript,let,提升,var,main,变量 From: https://www.cnblogs.com/euler0525/p/17660020.html