let和const是ES6中新增的声明变量的关键词,而var是ES5中声明变量的关键词。
现在我们通过代码来看一下var、let、const三者之间的区别。
举例
1. var声明的全局变量挂载在window中,会造成全局变量污染,而let和const不会。
// 1.var声明的全局变量挂载在window中,会造成全局变量污染
var num1 = 100;
console.log(num1)//100
console.log(window.num1)//100
// let声明不会挂载在window中,不会造成全局变量污染
let num2 = 99;
console.log(num2) //99
console.log(window.num2) //undefined
// const声明不会挂载在window中,不会造成全局变量污染
const num3 = 98;
console.log(num3) //98
console.log(window.num3) //undefined
运行结果:
通过结果我们发现,只有var声明的变量才能通过window打印出来,let和const打印出来的就是undefined,这说明它们并没有挂载在window中,也就不会造成全局变量污染了。
2.let和const新增一个块级作用域,放置在{}中,以前只有函数作用域和全局作用域。
var a = 10;
function fun(){
console.log(a);//undefined
if(true){
var a = 20;
}
console.log(a);//20
}
fun()
function fun1(){
let n = 5;
if(true){
let n = 6;
}
console.log(n);//5
}
fun1()
运行结果:
首先先看var声明的, if
代码块的外部使用外层的a
变量,内部使用内层的a
变量。但是,函数fun执行后,输出结果为undefined,原因在于变量提升,导致内层的a
变量覆盖了外层的a
变量。
let声明了变量n
,运行后输出 5。这表示外层代码块不受内层代码块的影响。如果两次都使用var
定义变量n
,最后输出的值才是 6。
块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了
在没学习es6之前,我们会遇到这种情况,现在我们用ul li显示1-10,10个数字,当点击任一数字时,就会显示那个数字的下标,用var如何实现呢?
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script>
// 解决i值问题
var lis = document.getElementsByTagName("li")
for(var i = 0 ; i < lis.length;i++){
lis[i].onclick = function(){
console.log(i)
}
}
</script>
运行结果:
如果我们使用上面那种方式,不管你点击几次,点击什么数字,var声明的就只会显示最后一个数字10,解决方法就是使用立即执行函数。
var lis = document.getElementsByTagName("li")
for(var i = 0 ; i < lis.length;i++){
(function(i){
lis[i].onclick = function(){
console.log(i)
}
})(i)
}
运行结果:
使用立即执行函数后,我们就会发现,当你点击哪个数字,就会显示哪个数字的下标。
但是使用let就不用使用立即执行函数也能解决那个问题了。
let lis = document.getElementsByTagName("li")
for(let i = 0 ; i < lis.length;i++){
lis[i].onclick = function(){
console.log(i)
}
}
运行结果:
这就是let的块级作用域的效果。
3.var可以重复声明,而let和const不允许重复声明。
通过下面代码我们就能发现,var重复声明就是后面覆盖前面的,而let和const通过下面的图就发现,当写出两个一样的名字就会直接提示你错误,都不需要运行了。
4.var可以声明提前,而let和const则不会
console.log(num)//undefined
var num = 100;
console.log(num1)//error
let num1 = 100;
console.log(num2)//error
const num2 = 100;e
运行结果:
通过结果我们会发现,var声明的变量先打印再赋值,显示的是undefined,为什么会显示为undefined,这就需要理解函数预编译AO和全局预编译GO了;而let和const则显示的是报错,也就是说let和const不能声明变量提前。
5.const声明和赋值必须一次性完成,而var和let则不用
通过上图我们发现,const先声明再赋值的话就会报错,而let和var则会正常输出结果。
6.const一经声明并赋值,不允许被修改,不允许改变内存空间地址
const qwe = "laila";
qwe = 123;
console.log(qwe)
运行结果:
const如果赋值后再修改值,就会报错。
总结
var:
- var声明的变量会挂在window中,容易造成全局变量污染;
- var可以重复声明同一个值,后一个var声明的值会覆盖之前的值;
- var有声明变量的提前,可以先使用后声明,let和const没有;
- var和let声明的是变量,可以被修改,const声明的是常量,不能被修改。
- var和let声明不需要必须赋值,而const在声明时必须赋值;
- var和let声明变量,const声明常量。
let:
- let声明的变量不会挂在window中,不会造成全局变量污染;
- 新增了一个块级作用域,放置在{}中,以前只有函数作用域和全局作用域;
- let不允许重复声明;
- let不会声明提前(只是人为看到的效果,实际上有声明提前,提前到临时性死区中)。
const:
- 和let四点一样,不能重复声明,不能声明提前;
- 不允许被修改,不允许改变内存空间的地址;
- const声明和赋值必须一次性完成,并且后期不允许改变存储空间的地址。
使用:能使用const尽量使用const,不能使用const就使用let,避免使用var,避免造成全局变量污染。