JS中的let与var的变量提升
实际上无论var,let,还是function都存在变量的三个过程,而const只存在前两个
- 创建 create
- 初始化 initialize
- 赋值 assign
1.声明var变量的过程
有如下代码(下面是函数作用域,不过var在全局声明也是同理)
function text(){
var num1 = 1;
var num2 = 2;
}
test();
在执行这个test函数时,会发生以下的过程,还有其他过程这里不详细说
进去test函数,为test函数创建一个环境
寻找函数中所有使用var关键字声明的变量并创建(create)这些变量
将这些变量的值初始化( initialize)为 undefined
-
执行代码
num1 = 1; num2 = 2;
num1变量赋值为1,num2变量赋值为2
从上面的过程我们可以得知,var声明的变量在JS引擎解析的时候会首先被创建并赋初始值undefined,即所谓的变量提升概念
2.声明function的过程
有如下代码
test();
function test(){
console.log("hello world!");
}
同样的JS引擎在解析代码时会有如下过程
- 找到所有用 function 声明的变量,在对应的环境中创建这些变量。
- 讲这些变量初始化并赋值为对应的函数体
- 执行test函数
由此可见function变量会在函数执行前就提前完成三个过程
问题来了如果var声明的变量名与function声明的函数名一样呢?
var test;
function test(){
conslole.log("hello world!");
}
console.log(test); // ƒ test(){
// conslole.log("hello world!");
// }
结果显而易见,秉承函数优先的原则,函数是直接在执行代码之前就被赋值了,相等于覆盖了undefined值,因此会打印函数
另一种情况
var test = 1;
function test(){
conslole.log("hello world!");
}
console.log(test); // 1
这种情况下相当于在执行test=1这个赋值语句代码之前,test变量的值是函数体,但执行了test=1之后,test变量的值被覆盖为1了,因此会打印1;下面例子可以证明
console.log(test); /* 执行赋值代码之前 打印函数体 ƒ test(){
conslole.log("hello world!");
}
*/
var test = 1;
function test(){
conslole.log("hello world!");
}
3.声明let的过程
初识let印象
- let 声明的变量的作用域是块级的
- let 不能重复声明已存在的变量
- let 有暂时性的死区,不会被提升
- let 全局变量不会是window的属性
如下代码
{
let num1 = 1;
num1 = 2;
}
由于let是块级作用域,我们只看{}里面的过程
- 找到块级作用域中所有用 let 声明的变量,在环境中创建这些变量
- 开始执行代码(注意现在还没有进行初始化)
- 执行 x = 1,将 x 初始化为 1(这并不是一次赋值,如果代码是 let x,就将 x 初始化为 undefined)
- 执行 x = 2,对 x 进行赋值为2
因此这便解释了为什么在let x之前使用x会报错的现象
{
console.log(x);
let x = 1;
} //Uncaught ReferenceError: Cannot access 'x' before initialization
仅由报错信息就可以看出,x没被初始化之前是不能被使用的,而let的初始化过程是必须通过执行相应的代码完成的,即形成了所谓的暂时性死区
let与for循环结合使用的奇效
// 有过JS基础的朋友应该知道如果循环体的循环变量是var 声明的 i ,那么一定会打印五次5
// 而用let声明后则会打印 0 1 2 3 4
var liList = document.querySelectorAll('li'); // 获取五个li
for( let i=0; i<liList.length; i++){
liList[i].onclick = function(){
console.log(i)
}
}
原理简单来说就是由于let的块级作用域特点,使得let声明的循环变量 i 在对应的循环体中都保存了对应的值,而且只有循环体内部能访问到这个值
const声明
const声明变量的过程只有创建和初始化两个步骤,声明同时必须初始化,之后不可再被赋值
const a = 1;
a = 2; //Uncaught TypeError: Assignment to constant variable. 报错 不能修改值
const a; //Uncaught SyntaxError: Missing initializer in const declaration 报错,没有初始化
其余特性跟let相同