前言 本想用一句话概括什么是"变量提升"方便读者了解,却发现这不是件简单的事情,并不是说"变量提升"有多难,主要是自身语言组织能力不强,所以先通过代码来了解吧!
var的变量提升
a = 2;
var a;
console.log(a); //2
var b;
console.log(b); //undefined
b = 2;
解说代码执行步骤:
- 首先是js预编译阶段搜集所有的变量声明并且提前声明变量 预编译代码变为:
//例一: var a; //此处声明位置往上提 var b;//此处声明位置往上提 a = 2; console.log(a); //2 console.log(b); //undefined b = 2;
- 初始化声明变量 a=undefined; b=undefined;
- 执行阶段 执行语句代码;也就是 a=2;console.log(a)..... 这些执行代码
以上 代码执行可以理解成: var 的「创建」(也就是声明)和「初始化」(都先初始为undefined)都被提升了
function的变量提升
test();//test
function test(){
console.log("test")
}
代码执行步骤:
- 在全局环境(window)中找到所有用 function 声明的变量,在环境中「创建」变量。
- 将这些变量「初始化」并「赋值」为 function(){ console.log("test") }.
- 开始执行代码test()
以上 代码执行可以理解成:function 声明会在代码执行之前就「创建、初始化并赋值」。
let的变量提升
let x = 'global'{
console.log(x) // Uncaught ReferenceError: x is not defined
let x = 1
let y;
console.log(y) //undefind
}
这里要注意的是 脚本是直接报错而非报undefined , 请看编译执行步骤解惑
代码执行步骤:
- 找到所有用 let 声明的变量,在环境中「创建」变量
- 开始执行代码(注意现在 let x 并没有像 var样有初始化为undefined的操作,所以不能使用x(也就是let ,const 所谓的“暂时性死区”,“暂时性死区”不是ECMAScript规范里的正式定义,它只是在程序员中广为流行而已))
以上 代码执行可以理解成:let 的「创建」过程被提升了,但是初始化没有提升
综上var function let 写了一个栗子,建议在console执行一遍 加深印象
var a=1
b = 2
foo()
function foo(){
console.log(a) //undefined
console.log(b) //Uncaught ReferenceError: b is not defined(报错)
let b = 3;
//let b = 4; //Uncaught SyntaxError: Identifier 'b' has already been declared(报错 let不能重复声明)
var a=c=2 //var 函数作用域变量
}
console.log(c); //2 c其实声明的是全局变量