1.var关键字
作用域:var定义的变量会成为包含它的函数的局部变量,不过定义变量时省略var操作符,创建的变量会变成全局变量可以在函数外部访问到。
function test(){ var a = 'a'; b = 'b'; }
test();
console.log(a);//报错
console.log(b);//'b'
var声明变量时会自动提升导函数作用域顶部
function test(){ console.log(a); var a = 'a'; }
test();//undefined
等价于
function test(){
var a;
console.log(a);
a='a';
}
test();
var允许多次声明同一个变量。
2.let声明
作用域:块作用域。
因为let声明的变量作用域仅限于该块内部,所以变量b不能在if块外被引用。 let不允许同一个作用域下出现冗余声明,会导致报错。
js引擎会记录用于变量声明的标识符及其所在的块作用域,因此嵌套使用相同的标识符不会报错,而这是因为同一个块中没有重复声明。
对声明冗余不会因为混用let和var而受影响。这两个关键字并不是声明不同类型的变量,它们只是指出变量在相关作用域如何存在。
暂时性死区
let和var存在的另一个重要的区别是let不会提升变量。
在解析代码是js引擎也会注意出现在块后面的let声明,只不过在此之前不能以任何方式来引用未声明的变量,在let声明之前的执行瞬间被称为“暂时性死区”,在此阶段引用任何后面才声明的变量都会抛出ReferenceError。
console.log(aa)//undefined
var aa = 'aa'
console.log(bb)//报错,bb没有定义
let bb = 'bb'
全局声明
与var关键字不同,使用let在全局作用域中声明的变量不会成为window对象的属性。(var声明的变量则会成为window对象的属性),不过let声明仍然是在全局作用域中发生的,相应变量会在页面的生命周期内延续,因此必须避免页面重复声明同一个变量。
var aa = 'aa'
console.log(window.aa)//'aa'
let bb = 'bb'
console.log(window.bb)//undefined
条件声明
在使用var声明变量时,由于变量声明会被提升,js引擎会自动将多余的声明在作用域顶部合并为一个声明。但是let的作用域是块,所以不可能检查之前有没有使用let声明过同名变量,同时也就不可能在没有声明的声明它。使用try/catch语句或typeof操作符也不能解决,因为条件块中let声明的作用域仅限于该块。
<script>
var name = 'nicholas';
let age = 26;
</script>
<script>
var name = 'mark';//这里没问题,可以被作为提示变量处理,不需要检查之前是否有同名变量
let age = 26;//age之前生命过这里会报错
</script>
for循环
使用var声明的for循环的迭代变量会渗透到循环体外部。let会使迭代变量的作用域仅限于for循环内部。
for(var i=0;i<5;i++){
}
console.log(i);//5
for(let i=0;i<5;i++){
}
console.log(i);//报错i没有定义
let还可以用于对迭代变量的奇特声明和修改,比如下面的代码
for(var i=0;i<5;i++){
setTimeout(()=>{console.log(i)},0)
}//你可能以为会输出0,1,2,3,4。实际输出5,5,5,5,5
之所以是这样,是因为在退出循环时保存的迭代变量是5,在执行之后的setTimeout时,所有的i都是同一个变量,所以输出的都是同一个值,而用let声明变量时,js引擎会为每个迭代循环声明一个新的迭代变量,所以setTimeout引用的是循环过程中的每个迭代变量的值。
for(let i=0;i<5;i++){
setTimeout(()=>{console.log(i)},0)
}//0,1,2,3,4
3.const声明
const的行为与let基本相同,但是const声明变量时必须同时初始化变量,且修改const声明的变量会导致报错。const也不允许重复命名。 作用域:块作用域。
const声明的限制只适用于它指向的变量的引用。如果const引用的是一个对象,修改对象内部的属性不会报错。
cosnt不能和let一样用来声明迭代变量,因为迭代变量会自增。但是const可以用来声明不会被修改的for循环变量,如for-of和for-in
const obj = {a:'a',b:'b'}
const arr = [1,2,3,4,5]
for(const key in obj){
console.log(key);
}//a,b
for(const key in arr){
console.log(key);
}//1,2,3,4,5