使用var关键字声明的变量,无论其实际声明位置在何处,都会被视为声明于所在函数的顶部(如果声明不在任意函数内,则视为在全局作用域的顶部)。这就是所谓的变量提升。
块级声明就是让所声明的变量在指定块的作用域外无法被访问。块级作用域在如下情况被创建:
let声明的语法和var的语法一致。基本可以使用let替换var,但会将变量的作用域限制在当前代码块中。let声明不会被提升到当前代码块的顶部。
如果一个标识符在代码内部被定义,那么在此代码块内部使用同一个标识符进行let声明就会导致抛出错误。
var count = 30;
let count = 40;//语法错误
如果在嵌套作用域内使用let声明一个同名的新变量,则不会抛出错误。
var count = 30;
if(condition){
let count = 40;//不会抛出错误
}
使用const进行常量的声明,它们的值在被设置完成之后就不能再被改变。正因为如此,所有的const变量都需要在声明时进行初始化
const MAX_ITEMS = 30;
const NAME;//语法错误
常量与let声明都是块级声明。与let声明类似,const声明会在同一作用域内定义一个已有变量时会刨除错误,无论改变了是var声明还是let声明。
var message = "HELLO";
let age = 25;
//二者都会抛出错误
const message = "Goodbye";
const age = 23;
let与const一个重大区别是:试图对之前用const声明的常量进行赋值会抛出错误,无论在严格模式还是非严格模式下
const maxItems = 30;
maxItems = 35;//抛出错误
但是如果const定义的常量如果是一个对象,它所包含的值是可以修改的。
var const person = {
name = "cc"
}
//正常工作
person.name = "dd";
//抛出错误
person = {
name = "aa";
}
let和const不同于var的另一个方面是在全局作用域上的表现。当在全局作用域上使用var时,它会创建一个新的全局变量,并成为全局对象(在浏览器中是window)的一个属性。这意味着使用var可能会无意覆盖一个已有的全局属性。
var RegExp = "hello";
console.log(window.RegExp);//"hello"
var ncz = "hi";
console.log(window.ncz);
在全局作用域上使用let或const,虽然会在全局作用域上创建新的绑定,但不会有任何属性被添加到全局对象上。这也就意味着你不能用let或const来覆盖一个全局变量,你只能将其屏蔽。
let RegExp = "hello";
console.log(window.RegExp);//function
console.log(window.RegExp === RegExp);//false
const ncz = "hi";
console.log(ncz);//hi
console.log("ncz" in window);//false
随着更多的开发者迁移到es6上,一种替代方案变得更为流行,那就是在默认情况下使用const,并且只有在知道变量值需要被更改的情况下才使用let。其理论依据是大部分变量在初始化之后都不应当被修改,因为预期外的改动是bug的源头之一。