**出现的时期 **
var -->ES5
let const -->ES6
块级作用域
ES6以前JS以var来声明变量,以function来区分作用域,{}这种无法限定var的作用域。
ES6出现后,带来了块级作用域。if,for等可以产生一个花括号,花括号中的语句集合都属于{块}
,在块中定义的变量在块外是不可见的,我们把从 ' { '
开始 ' } '
结束的这一块称为块级作用域。
在块级作用域里,和函数作用域有相类似的地方,那就是当函数调用完成后,函数内部的变量会被销毁。那么块级作用域……请看例子!
function test(){
(function(){
for(var i=0;i<10;i++);
})();
console.log(i);
}
test();
想想看会输出什么?结果是 i
未定义。为什么呢?这是因为js的闭包特性,for
语句在闭包内,当function被调用结束后,i被销毁,所以访问不到。
暂时性死区
暂时性死区(TDZ)是真正短暂的(基于时间),和不受空间条件限制的(基于位置)。
if(true){
const fun = function(){//TDZ begin
console.log(myVar);//OK
}
…
let myVar = 3;//TDZ end
fun();//TDZ 外部
}
变量提升
函数提升是把后面的变量都提到前面去。
这个还是用例子来说
function test(){
console.log(say);
var say = ' Hello ! ' ;
}
不会报错,输出undefined;
因为变量提升,会将上面的变成
function test(){
var say;
console.log(say);
say = ' Hello ! ' ;
}
这个还是非常好理解的,如果你还在使用ES5的话,那就在书写的时候最好自己手动提升,这样,编程的时候不容易出错。
函数提升
函数提升是把整个函数都提到前面去。
function test(){
fun();
function fun(){
alert("fun");
}
}
test();
但是这样却不行
function test(){
fun();
var fun =function f(){
alert("fun");
}
}
test();
WHY?
因为,JS中函数的写法,一种是函数表达式,另外一种是函数声明方式。只有函数声明形式才能被提升。
三者的区别
-
let:
作用域是块级,不能在同一块级作用域中重复声明,拥有暂时性死区,没有变量提升。
当进入let作用域,立即创建存储空间;获取或设置未初始的变量会抛异常,Reference error;当执行到变量声明的时候,若定义了值就赋值,若没有值,那就是udefined,变量在暂时性死区不能被访问,所以无法对它使用typeof。 -
const:
作用域是块级,不能重复声明,并且声明的同时就要赋值,拥有暂时性死区,声明常量。
在暂时性死区内它不能被访问(获取或设置)直到执行到达声明。 -
var:
作用域是函数作用域,可以重复声明,没有暂时性死区,有变量提升。
当进入var的作用域,立即为它创建存储空间,变量会立即被初始化并赋值为undefined,当执行到变量声明的时候,若变量定义了值则会被赋值。