ES6中提供了let关键字,跟var很相似,它们主要有以下几点区别
1、重复定义
var定义的变量可以进行重复定义,后面定义的值会将前面定义的覆盖
var i = 1;
var i = 2;
console.log(i);
let不允许重复定义
let i = 1;
let i = 2;
console.log(i);
2、全局作用域
在非严格模式下,通过var定义的变量会在全局作用域下绑定到当前的window对象上(严格模式和非严格模式可以自行百度了解)
var i = 1;
console.log("i" in window);
console.log(window.i);
而let定义的变量不存在window对象中
let i = 1;
console.log("i" in window);
console.log(window.i);
3、变量提升和暂时性死区
var和let定义的变量都会存在变量的提升,在全局作用域和函数作用域里面变量都会被提升到全局作用域或者函数作用域的顶部
比如下面这段代码
console.log(i);
var i = 1;
console.log(i);
实际上经过变量提升后是这样
var i = undefined;
console.log(i);
i = 1;
console.log(i);
两个运行的结果都是
但是let在定义的时候会出现暂时性死区,如果在定义前访问,相当于在这个暂时性死区里来访问这个变量
console.log(i);
let i = 1;
会报出错误
实际上这个变量已经被提升到顶端了,但是这个提升在到达或执行完这个语句之前所有对这个变量的访问都是不允许的,因为这个时候是在暂时性死区里面访问
4、作用域
var定义的变量有函数作用域和全局作用域,let除了函数和全局这两个作用域还有块级作用域的概念
var
var i = 1;
function fun(){
var i = 2;
}
fun();
console.log(i);
if(true){
var i = 3;
}
console.log(i);
因为var有函数作用域的概念,在不同的函数里可以有同样名称的变量,所以上面代码的函数fun不会改变外面的i,因此首先输出的是1,但是var没有像if这样的块级作用域,所以按照顺序,下面的会替换掉上面的,因此得到的是3
let
let i = 1;
if(true){
let i = 2;
}
console.log(i);
let具有块级作用域的概念,也就是两个大括号{}之间,只在这一块中起作用,因此不会改变外面的i
另外,块级作用域还有我们常用的for循环等
for(var i = 0; i < 5; i++){
}
console.log(i)
for(let j = 0; j < 5; j++){
}
console.log(j)
Tips:事实上var可以算是JavaScript设计上的bug,但这种错误大多不能修复和移除,需向后兼容,后来就出现了let关键字,可以将let看成是更完美的var,因此实际上用let来代替var比较好,使用let取代var是趋势,另外还有const关键字,const跟let差不多,只不过const用来定义常量,不可改变它的值(实际上是变量指向的内存地址不得改动),let用来定义变量,且const在定义常量时就要赋值,否则会报错。