ES6中新添加了两种声明变量的方式:let、const。对比原有的变量声明方式 var,它们有以下区别:
一、let与var的区别
1、let声明的变量,不会提升,var反之。
function foo(){
console.log( a ); //Uncaught ReferenceError: a is not defined 未定义
let a = 2;
}
function foo(){
console.log( a ); //undefined 未赋值
var a = 2;
}
2、let不允许在相同的作用域内,重复声明同一个变量,var可以。
//错误一
{
let a=1;
let a=2; //Identifier 'a' has already been declared 标识符“a”已被声明
console.log(a);
}
//错误二
{
let a=1;
var a=2; //Identifier 'a' has already been declared 标识符“a”已被声明
console.log(a);
}
//var 重复声明时,后声明的值覆盖前声明的值
{
var a=1;
var a=2;
console.log(a);//输出2
}
注意:
(1)for循环中,小括号里的部分与花括号里的部分不是一个作用域,可以理解为他们是嵌套关系,小括号是父作用域,花括号是子作用域,所以,下面这段代码不算是重复定义变量:
for(let a=0;a<5;a++){
let a=6;//不报错
}
(2)注意区别函数与for循环,函数参数默认已经定义了,不能使用let、const声明:
function my(b='小杨'){
let b='小张';
console.log(b);//Uncaught SyntaxError: Identifier 'b' has already been declared
}
my();
3、let实际上是JavaScript增加的块级作用域。所声明的变量只在let命令所在的代码块内有效。
function foo(){
let a=1;
if (true){
let a=2;
}
console.log(a);//输出1,外层代码块不受内层代码块的影响
}
function foo(){
var a=1;
if (true){
var a=2;
}
console.log(a);//输出2
}
再看下面这段代码:
var a = [];
for(var i = 0; i < 10; i++) {
var c = i;
a[i] = function(){
console.log( c );
};
}
a[6](); //9 var定义的i是全局变量,每一次循环之后,i的结果会影响到之前循环后的结果,在这调用的函数输出的是for循环执行到最后的结果。
改成let声明:
var a = [];
for (var i = 0; i < 10; i++) {
let c = i;
a[i] = function(){
console.log( c );
};
}
a[6](); //6 let定义的i只在块级作用域中起作用,每一次循环,都是一个新的块级作用域,每次循环产生的块级作用域之间互不影响。
4、关于全局对象属性
在ES5中,全局对象的属性和全局变量是等价的。ES6规定,使用var, function声明的全局变量依旧作为全局变量的属性存在,而使用let,const,class声明的全局变量则不属于全局变量的属性。
var foo = 'foo';
let bar = 'bar';
foo === window.foo; // =>true
bar === window.bar; // => false
二、const与var的区别
1、const与let的特性基本相同,但顾名思义,const用于声明常量,一旦声明,必须立即赋值,且以后不可更改。
const a=1;
console.log(a);//输出1
a=2;
console.log(a);//报错
const a=3;
console.log(a);//报错
2、const定义的对象是可以修改的,比如:
const a=['qqq','wwww'];
a.push('nnn');
console.log(a);//输出["qqq", "wwww", "nnn"],是不报错的
要想定义的对象不能修改,可以这样做:
const a=Object.freeze(['qqq','wwww']);
a.push('nnn');
console.log(a);//报错,被冻结的对象不能修改
三、小结
ES5中只有两种声明变量的方式:var、function,ES6种添加了四种声明变量的方式:let、const、class、import(后续会进行介绍)。
let可以完全取代var,因为二者作用几乎相同,且let没有任何副作用。在let和const之间,优先使用const,尤其是只应该设置常量的全局环境。大部分的函数一旦定义就不会改变(除了使用初始化分支的方式覆写函数的时候),所以,我们一般推荐使用const来声明一个函数。最后,V8只在严格模式下支持let和const的声明方式。
最后再对let/const和var的区别进行一下汇总,使用let声明的变量:
隶属于块级作用域,块级作用域外不可见
不存在“变量提升”
同一作用域内不得存在名称相同的变量
当声明为全局变量时不会作为全局对象的属性
网友评论