var声明提前(Hositing)机制
详细了解变量提升,戳这里
var + 函数内部/全局 = > 提升。
提升导致了像if语句、for循环等等内部的变量都会被提出来。这些事我们不期望的。如果if语句没有执行到,但是这个变量却依然提前被声明了,声明就意味着提前开辟了空间,由于作用域是函数作用域,在if之外依然可以使用它。
为了解决这个问题,块级作用域就应运而生了。
块级声明
为了让块内的变量在块外无法访问。
let声明
1、不会被提升
2、不可以重复声明
3、创建块级作用域,块级作用域之外立刻销毁。
重复声明的例子:
var a = 0;
let a = 1; // 报错
let a = 0;
let a = 1; // 报错
var a = 0;
if(true){
let a = 1; // 正常不报错,属于新的块
}
const声明
1、常量,且必须在声明时初始化,不可再赋值。
2、不可重复声明,例子与上例相仿。
3、创建块级作用域,块级作用域之外立刻销毁。
临时死区(TDZ)
JS引擎扫描代码时,如果是var声明的,提升,如果是let const 放到TDZ中,访问TDZ中的变量会触发运行时错误。
例子
console.log(typeof a); //undefined
if(true){
console.log(typeofb); // 引用报错
let a;
let b;
}
循环
funcs = [];
for(* i=0;i<10;i++){
funcs.push(function (i){
console.log(i)
})
}
循环中var:输出十个10 执行时访问的时当前作用域中的i 每个执行时i都是10 改进 :立即执行的函数 输出0-9
循环中的let: 输出0-9 循环时会创建一个新的变量i,并初始化为当前i的值后使用该作用域内部的i。 此时的i时当前块级作用域的i 可以理解成转为if语句
循环中的const : 输出0 然后报错 与let一致,但是const 声明的i不允许更改,因此i++时就会报错。
全局作用域绑定
var :挂载到window上,如果需要跨frame 跨window访问,仍然是一种办法。
let :不会挂载到window上,不会污染或者破坏全局作用域。 更安全。
最佳实践
默认const 需要改变let 解决特殊问题var