let/const 不存在变量提升,不允许在声明之前使用
console.log(a);
let a = 1;
报错 「Uncaught ReferenceError: Cannot access ‘a’ before initialization」。
这是为什么了?其实最开始浏览器从服务器获取的js都是文本(字符串),声明的文件格式「content-type: application/javascript」。浏览器首先按照这个格式去解析代码,也就是进行「词法解析」生成 AST 语法树。
基于 let、const 等声明的变量,在词法解析阶段就已经明确在此上下文中未来一定会存在这些 let、const 声明的变量,在代码执行时,如果在具体声明的变量之前使用了这些变量,浏览器就会报错「Uncaught ReferenceError: Cannot access ‘a’ before initialization」。所以说 let 、const 类似会有一种变量提升,但是本质上并不是变量提升。
let/const 不允许重复声明
在同一上下文中,无论当前基于何种方式声明过变量,都不允许重复声明。var 是可以重复申明的,词法解析可以审核通过,执行阶段遇到已经申明过的,不会重复申明,但是let不行,在词法解析阶段都过不去,不也存在引擎去执行代码的阶段了。
let 不会污染全局
在全局上下文中,基于 var / function 声明的变量,是给 window(GO) 设置属性,基于 let / const 声明的变量是 VO(G) 中,和 GO 是没有关系的。
var a = 1;
window.a // 1
let a = 1;
window.a //undefined
const a = 1;
window.a //undefined
let/const 会生成块级上下文
for(let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, 10);
}
// let的实现原理其实和闭包是一样的
{
// 1、let会先形成一个父块作用域,计数器累加
let i = 0;
{
// 每一次循环形成一个子块级作用域
let i = 0; // i每次递增
setTimeout(() => {
console.log(i);
}, 10);
}
i++;
}
let / const 会形成暂时性死区
所谓暂时性死区就是在定义之前使用 let / const 的变量会报错
let VS const
let、const 都是ES6新增声明的变量的语法,区别是 let 创建的变量是可以更改指针指向,也就是可以重新赋值,但是const申明的变量是不允许改变指针指向的。