说明:除了提供var的变量声明方法,
还提供了将变量绑定到所有的任意作用域中(通常是{..}内部)
换句话说:let,为其声明的变量隐式劫持了所有的块作用域
块作用域
ES5中:只有全局作用域和函数作用域
说明:花括号{..}包括的代码
但是:for while if中并没有块级作用域
解决:使用let 声明 或 使用闭包包裹
for(var i = 0; i < 5; i++){
var a = 10;
let b = 2333;
}
// 貌似i和a 都定义在for的作用域内
// 实质是绑定到全局变量中
console.log(i, a) // 6 10
console.log(b) // ReferenceError: err not found
提升 编辑器的预编译
var 变量:声明会被提升,赋值则不会
let 变量:不会被提升
函数:会被提升
函数优先:函数相对于变量优先提升
console.log(a) // undefined
var a = 2; //a以被声明并赋值undefined 但未赋值2
b() // 2
function b(){ console.log(1) }; // 被提升
function b(){ console.log(2) }; // 被提升并覆盖上个
var b = function(){console.log(3)}; // 有函数被忽略
c() // TypeError
// c变量声明被提升,但未赋值。 undefined不能运算操作
var c = function(){console.log(1)}
let 和 for
for 和 var:for本省没有块作用域 需要使用闭包来来保存每一次的循环变量。
(循环变量)和{循环体}是父子作用域关系,在循环体内重复声明i不会影循环变量
for 每一次迭代:获取上一次循环变量,并从新声明新
当for使用let:由于每一次都是新的let声明,所以都是新的块作用域
// 用let 声明 i 让 i 成为块级作用域形成变量,
// 每一次的 i 只对当时的块作用域内有效。
for(let i = 0; i < 3; i++){
setTimeout(()=>{
console.log(i) // 0 1 2
},1000)
}
for(let i = 0; i < 3; i++){
let i = 'abc'; //声明 i 但不会覆盖 循环变量里面的i
setTimeout(()=>{
console.log(i) // 'abc' 'abc' 'abc'
},1000)
}
暂时性死区 不能重复声明
说明:只要块级作用域内存在let变量,该声明的变量名不受外部的同名变量影响
使用:在变量正式被声明前,不能使用
let a = 10;
function foo(){
// a 被绑定,且let不会被提升
console.log(a);// ReferenceError
let a = 20; //let声明 的a变量,以上区域为死区
let a = 30; // SyntaxError 重复声明报错
};
foo();