在js中只支持全局作用域和函数作用域,并不支持块级作用域。ES的let解决了这个问题。
let,const与JS中的var有相似也有不同,它们同时可以用来声明变量,不过也有一些不同之处,具体表现在以下几点:
- var 支持变量提升,即在声明变量之前可以使用变量;但是const,let不支持变量提升,严格要求在使用变量之前必须要声明变量,否则会报错。
- let 在同一个作用域内不能声明2个或2个以上相同的变量;
const 支持声明常量,常量一旦声明之后不可修改。这里的不可修改指的是变量指向的地址不可修改。如:boolean,string类型值不可修改,但是当用const声明对象和数组时就可以添加、删除或者修改对象的属性。
const fo={}; fo.prop=123; fo.prop //123
let,const都只支持块级作用域,在块级作用域外不能访问到let,const声明的变量。这很有效的解决了因循环变量的使用而造成的全局变量泛滥的 情况。下面有一个与JS大有不同的例子,晒出来大家可以看看。
var a=[]; for(var i=0;i<10;i++){ a[i]=function(){ console.log(i); } } a[6](); //10
var a=[];
for(let i=0;i<10;i++){
a[i]=function(){
console.log(i);
}
}
a[6](); //6
造成以上不同的原因是var声明的是全局变量,在闭包里使用的i只可以访问到最后的值,所以会输出10;而用let声明的变量,在每一次循环时都会重新进行初始化,大家可能会疑惑那怎么会在原来循环的基础上加1,这是因为JS内置引擎的原因,它会记住上一次的循环值,在原来循环值的基础上加1.
使用let需要注意的问题:
当某作用域内存在使用let声明变量时,则变量在该作用域内存在,只不过在let声明变量的语句后,该变量才可以获取和使用。
在ES中不建议在块级作用域内声明函数,如果有必要那样做的话,尽量使用函数表达式而不是函数声明。ES6中在块级作用域内声明函数,会将函数声明当做let声明,该函数在块级作用域外不起作用。但是浏览器可以不遵守这个规定,在支持ES6的浏览器中,
(1) 允许在块级作用域中声明函数;
(2) 会把函数声明提前到块级作用域,全局作用域,函数作用域的开头。
(3) 当在块级作用域中对之前的函数进行重写,虽然块级作用域后,在块级作用域内声明的函数不起作用,但是还是会对之前的函数造成影响,常常会报错。
而ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数。