var与let的区别

var

var 声明的变量是函数作用域变量。

1
var a = 1;
2
var a = 2;
3
等价于
4
var a;
5
var a;
6
a = 1;
7
a = 2;

var 声明的变量提到作用域的前方,简称变量提升。

看一个例子

1
var a = 1;
2
function foo(){
3
  alert(a);
4
  var a = 2;
5
}
6
foo.call()

alert(a)打出来的是什么?

我们先做一下转换,先找声明,把声明提升到作用域的前方,再看代码。

1
var a;
2
function foo(){
3
  var a;
4
  alert(a);
5
  a = 2;
6
}
7
a = 1;
8
foo.call()

转换后的代码,我们就一目了然了,alert(a)打出来undefined

1
function f1(){
2
  if(true){
3
  }else{
4
    var a = 1
5
  }
6
  alert(a)
7
}
8
f1();

跟前面一样,先找声明,把声明提升到作用域的前方,再看代码。

1
function f1(){
2
  var a;
3
  if(true){
4
  }else{
5
    a = 1
6
  }
7
  alert(a)
8
}
9
f1();

此时的alert(a)也是undefined。

1
for(var i = 0;i < 6;i++){
2
  setTimeout(function(){
3
    console.log(i)
4
  },1000)
5
}

打印出i的值是什么呢?
先把声明提升上去,再看代码,1s之后for循环早已执行完毕,此时i的值为6,再执行函数,结果console.log(i)就是6个6。

let

let 声明的变量是块级作用域变量。
let 无法重复声明
let 和 for 循环一起使用有奇怪现象
let 声明的变量提升到块级作用域的第一行
实际声明的一行与块级作用域第一行之间的区域,就是该let 变量的TDZ(临时死亡区域)

1
let a = 1;
2
let a = 2; 
3
//Uncaught SyntaxError: Identifier 'a' has already been declared

重复声明会报错

1
for(let i = 0;i < 6;i++){
2
  setTimeout(function(){
3
    console.log(i)
4
  },1000)
5
}

打印出i的值是什么?打印出0 1 2 3 4 5,结果跟我们想的一样,但过程却不一样。

变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量

1
let a = 1;
2
{
3
  console.log(a);
4
  let a = 2;
5
}

console.log(a)会打出什么呢?

先做转换,再代码。

1
let a;
2
a = 1;
3
{
4
  let a;
5
  console.log(a);
6
  a = 2;
7
}

转换完,感觉console.log(a)是undefined.再看看let的第五大特性,console.log(a)这行代码就是TDZ(临时死亡区域),所以执行的结果会报错。
先let声明变量,再使用。