let与var的区别

3,927 阅读2分钟

let为ES6新增的用来声明变量的命令,用法类似与var,那么let和var具体是怎么个用法以及他们之间有什么区别呢?

一. let声明的变量只在let代码块有效

{
    let a = 1;
    var b = 2;
}
console.log(a); // 报错,a is not defined
console.log(b); // 2

用let声明了变量a,用var声明了变量b,输出的时候a报错,b输出了正确的值,这说明let只在它所在的代码块内有效。

实例:

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10

var声明变量是全局范围内有效的,虽然每次循环i都在改变,但是循环内都赋值给了a的i,相当于每次循环出来的i都是指向同一个i,也就是最后一个i,所以为10;

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

let声明的变量i只在本轮循环有效,每次循环的i都是一个全新的变量,所以值为6;


二. 不存在变量提升

console.log(foo); // 输出undefined
var foo = 2;
console.log(bar); // 报错ReferenceError
let bar = 2;

var会有变量提升,所以在输出foo之前,foo由于变量提升,就已经存在了,但是没有值,所以为undefined;let不存在变量提升,输出bar之前还未定义bar,所以报错。


三. 暂时性死区

var tmp = 123;
if (true) {
  tmp = 'abc';
  let tmp;
  console.log(tmp); // ReferenceError
}

var tmp = 123;
if (true) {
  tmp = 'abc';
  var tmp;
  console.log(tmp); // abc
}

全局声明了变量tmp,但是在代码块中又用let声明了tmp,使得后者绑定了块级作用域,此时的tmp是在声明之前就赋值了,所以报错。在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。


四. 不允许重复声明

{
  let a = 10;
  var a = 1;
  console.log(a); //报错
}

{
  let a = 10;
  let a = 1;
  console.log(a);//报错
}

{
  var a = 10;
  var a = 1;
  console.log(a); //1
}

let不允许在函数内部重复声明同一个函数,否则会报错。