前言
如果使用关键字var声明一个变量,那么这个变量就只有通过var关键字,函数声明是通过function关键字,而在es6之后,声明的方式有var,let,const,function,class等。
var let const
var
var声明的关键字存在变量提升
如果使用关键字var声明一个变量,那么这个变量就属于当前的函数作用域,如果声明是发生在任何函数外的顶层声明,那么这个变量就属于全局作用域,举例说明:
var a = 1; //此处声明的变量a为全局变量
function foo(){
var a = 2;//此处声明的变量a为函数foo的局部变量
console.log(a);//2
}
foo();
console.log(a);//1
如果在声明变量时,省略var的话,该变量就变成全局变量,如全局作用域中存在该变量,就会更新其值,如:
var a = 1; //此处声明的变量a为全局变量
function foo(){
a = 2;//此处的变量a也是全局变量
console.log(a);//2
}
foo();
console.log(a);//2
提升
提升是指无论var出现在一个作用域的哪个位置,这个声明都属于当前的整个作用域,在其中到处都可以访问到,注意只有变量声明才会提升,对变量赋值不会提升变量。如下所示:
console.log(a);//undefined
var a = 1;
该代码段跟下列代码段是一样的逻辑
var a;
console.log(a); // undefined
a = 1;
而如果对未声明过的变量进行操作,就会报错
console.log(b); // 假设b未声明过,Uncaught ReferenceError: b is not defined
let
let声明的变量,具有以下几个特点:
1,let声明的变量具有块级作用域的特征
2,在同一块级作用域,不能重复声明变量
3,let声明的变量不存在变量提升,即let声明存在暂时性死区。
例子:
let a = 1;
console.log(a);//1
console.log(b);//Uncaught ReferenceError: b is not defined
let b = 2;
function foo(){
let a = 1;
let a = 2;//Uncaught SyntaxError: Identifier 'a' has already been declared
}
以下为一个经典的关于var和let的一个例子:
for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
},100)
};
该代码运行后,会在控制台打印出10个10.若修改为:
for (let i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
},100)
};
则该代码运行后,就会在控制台打印出0-9.
const
const声明方式,除了具有let的特点外,还具备一个特点,即const定义的变量,一旦定义后,就不能修改,即const声明的为常量。
例如:
const a = 1;
console.log(a);//1
a = 2;
console.log(a);//Uncaught TypeError: Assignment to constant variable.
但是,并不是说 const 声明的变量其内部内容不可变,如:
const obj = {a:1,b:2};
console.log(obj.a);//1
obj.a = 3;
console.log(obj.a);//3
所以准确的说,是 const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。
总结:
1.var声明的变量属于函数作用域,let和const声明的变量属于块级作用域
2.var存在变量提升现象,而let和const没有
3.var变量可以重复声明,而在同一个块级作用域,let变量不能重新声明,const变量不能修改。
(1)块级作用域:块作用域由 { }包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题:
内层变量可能覆盖外层变量
用来计数的循环变量泄露为全局变量
(2)变量提升:var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否则会报错。
(3)给全局添加属性:浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。
(4)重复声明:var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的变量。const和let不允许重复声明变量。
(5)暂时性死区:在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。
(6)初始值设置:在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
(7)指针指向:let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。