一、作用域
在以前的ES5中,作用域只有全局作用域和函数作用域,没有块级作用域。
在函数作用域或全局作用域中通过关键字var声明的变量,无论实际上是在哪里声明的,都会被当成在当前作用域顶部声明的变量,这就是我们常说的提升(Hoisting)机制。
// 例:提升机制
function getValue(condition) {
if (condition) {
var value = 'blue';
return value
}else {
// 此处可访问变量value,其值为undefined
return null
}
// 此处可访问变量value,其值为undefined
}
这会导致函数作用域覆盖了全局作用域;亦或者循环中的变量泄露为全局变量。因此在ES6新添加了块级作用域的概念。
二、块级作用域
块级声明用于声明在指定块的作用域之外无法访问的变量。块级作用域(亦被称为词法作用域)存在于:
* 函数内部
* 块中(字符 { 和 } 之间的区域)
在ES5中,函数只能在顶级作用域和函数作用域中声明,不能在块级作用域中声明。但是在ES6中,函数可以在块级作用域中声明。
三、let命令
let命令的用法与var类似,最大的区别在于let所声明的变量只在let命令所在的代码块内有效。
// 例:let与cont区别
{
let a = 1;
var b =2;
console.log(a) // 1
console.log(b) // 2
}
console.log(a) // ReferenceError: a is not defined
console.log(b) // 2
如果你想要声明的变量绑定在声明它的地方的话就可以使用let命令去定义这些变量。
由于let声明不会被提升,因此开发者通常将let声明语句放在封闭代码块的顶部,以便整个代码块都可以访问。
:
letb不容许在相同作用域内重复声明同一个变量,此时再使用let声明就会抛出错误。因此,不能在函数内部重新声明参数
var a = 1;
// 抛出语法错误
let a = 2;
:(temporal dead zone,简称 TDZ)
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受到外部影响。
四、const命令
使用const声明的是常量,其值一旦被设定后不可更改。因此,每个通过const声明的常量必须进行初始化
const a = 1;
// 语法错误:常量未初始化
let b;
const声明不允许修改绑定,但允许修改值。这也就意味着用const声明对象后,可以修改对象但属性值。
const arry = [];
arry.push(1);
arry.push(2);
// arry [1,2]
arry = []
//抛出错误
五、const命令和let命令
const跟let特性一致的地方
const与let声明的都是块级标识符,所以常量也只在当前代码块内有效,一旦执行到块外会立即被销毁。常量同样也不会被提升至作用域顶部。
cons跟let特性的区别
let虽然不能重复声明,但是可以无限制的赋值,但const只能初始化的时候赋值一次。