在js中,常用的声明方式有:var、let、const。在es5中我们常用var声明变量,而在es6中新增了2种声明变量的方式为let和const,那么对于这三种声明变量的方式有何区别呢?
var
在es5中,我们将作用域分为全局作用域和局部作用域,其中局部作用域也叫作函数作用域,其主要以函数function来划分作用范围,而var对应声明的变量也叫做全局变量和局部变量,全局变量在全页面的任何位置起作用,而局部作用域只能在当前作用范围起作用。
var a = 10;
console.log(a); // 10
function fn(){
console.log(a); // 10
var b = 20;
console.log(b); // 20
}
fn();
console.log(b); // 报错: b is not defined
let
在es6中,新增了let用来声明变量,它的作用范围为块级作用域,出了当前块即不可再使用。
但是对于let来说,是不可以在一个块级作用域中,重复声明变量的,否则会报错,而var则不会。
{
var c = 30;
console.log(c); // 30
}
console.log(c); // c is not defined
const
const在es6中作用为声明一个常量,此常量意味着这个值是不可以被改变的,但是如果是引用数据类型则只要数据地址不变,即为未变,这与引用数据类型在内存中存储数据的方式有关。
const d = 30;
console.log(d); // 30
d = 40; // 报错: Assignment to constant variable
console.log(d);
引用数据类型:
const obj = {
name: '小可爱',
age: 33
};
obj.height = 40;
console.log(obj); // {name: '小可爱', age: 33, height: 40}
var 与 let的区别
解析顺序
var声明的变量在未声明之前使用,不会报错,结果为undefined;
而let则会行程暂时性死区,在声明之前使用会报错。
console.log(d); // undefined
var d = 40;
console.log(m); // 报错: Cannot access 'a' before initialization
let m = 50;
形成此种结果的原因是因为js代码在解析的时候,var变量声明会提升至顶部执行,而let虽然会声明提前,但是在声明之前不可使用此变量,形成一个封闭的区域,在声明之前使用报错。
作用范围不同
var为函数作用域,let为块级作用域,最明显的例子就是for循环中变量的影响。
for(var i = 0; i < 10; i++){
console.log(i);
}
console.log(i); // 10
for(let j = 0; j < 10; j++){
console.log(j);
}
console.log(j); // j is not defined
尤其是在for循环所嵌套的事件中,var声明的变量i在事件中无法得到正确的值,而let的则可以。
var lis = document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++){
lis[i].onclick = function () {
console.log(i); // 5
};
}
for(let j = 0; j < lis.length; j++){
lis[j].onclick = function () {
console.log(j); // 0 1 2 3 4
};
}