ES6中新增了let和const声明变量,那么let变量和var声明变量有什么区别呢?在实际开发中,应该选择哪一种声明变量的方式?
一、let不能重复声明变量
使用var重复声明变量时,后面的值会覆盖前面变量的值,比如:
var a= 10;
var a= 50;
console.log(a)//可以运行,输出为50。
使用let重复声明变量时,则代码会报错,比如:
let a= 10;
let a= 50;
console.log(a)//报错,没有输出
二、let不能在声明变量前使用变量
也就是说,在变量未声明之前是不能使用该变量的,但是在v8解析js代码时,函数调用栈创建代码执行上下文时,在词法环境还是会先创建变量,只是不能被访问。代码示例:
console.log(a);
let a = 10;//Uncaught ReferenceError: Cannot access 'a' before initialization
使用var时,则可以在声明变量前使用变量,var声明变量时,词法环境会先创建变量且可以访问。只不过会输出undefined.
console.log(a);
var a = 10;//undefined
三、let/const没有作用域提升
在ES6之前,只有全局作用域和函数作用域。在ES6的新特性中,增加了块级作用域代码快的概念,可以直接使用{代码快}创建块级作用域,该作用域对let/const/function/class声明的类型是有效的,这句话的意思即,对于作用域中使用let关键字声明的变量,外层是不可以访问的,而var声明的变量,外层可以访问。举个例子:
{
let a = 10;
}
console.log(a);//Uncaught ReferenceError: a is not defined
而使用var在let中声明变量时,则块级作用域不生效,即有{}和没有{}是一样的,var在{}创建的变量相当于在全局作用域里。如下:
{
var a = 10;
}
console.log(a);//输出10
四、const声明数组和对象,可以修改里面的内容
const声明单个数值或字符串时,如果后面重新对该变量进行赋值,则会报错。举个例子:
const a =5 ;
a=10;//moni.html:77 Uncaught TypeError: Assignment to constant variable.
const a = hello;
a=world;Uncaught ReferenceError: hello is not defined
但是对于数组和对象,则可以通过数组的push方法修改里面的内容。举个例子:
const arr= ['a','b','c']
arr.push('d');
console.log(arr);//输出['a', 'b', 'c', 'd']
可以使用push/pop等方法修改里面的内容,但是不能将另外一个数组赋值给该变量,举个例子:
const arr= ['a','b','c']
arr = ['b','c','d'];//Uncaught TypeError: Assignment to constant variable.
对象同理:
const obj ={
name : '蔡文姬',
age : 18
}
obj.address='beijing';
console.log(obj);//输出{name: '蔡文姬', age: 18, address: 'beijing'}
五、案例分享:for循环中的点击事件
给四个按钮添加点击事件 使用var 声明时,
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
console.log("第" + n + "个按钮被点击")
}
}//无论点击哪个按钮,都会输出第四个按钮被点击了,
使用let声明时:
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
console.log("第" + i + "个按钮被点击")
}
}//点击哪个按钮,输出哪个按钮。
为什么会出现以上现象呢,因为使用var声明时,i是一个全局变量,for没有形成块级作用域,i++最终是4,function执行时,会往上层作用域找i,此时会找到全局作用域i,也就是4,所以无论点击哪个按钮,都会输出第四个。 而使用let创建变量时,会在for循环中形成块级作用域,function会直接找到btns[i],则可以依次输出。
六、总结
在实际开发中,尽量使用let和const,不使用var如果确定后面会更改变量的值,则使用let,如果不确定会不会修改变量,都尽量使用const。