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声明变量,再使用。