目前在重看阮一峰老师的 ECMAScript 6 入门),打算将看到的知识点总结概括。es6
不论在面试的过程当中仍是在对代码进行 lint 的过程当中总过看到关于 let & const & var 的一些声明的异同的问题,如今就借助阮一峰老师的书籍对这些知识进行总结概括。面试
let
命令所声明的变量必定要在声明后使用,不然报错。浏览器
官方的说法是在 let 声明一个变量以前使用它是会发生错误。官方没有说到会发生变量提高(hoisting),可是有这样的两种现象,在 let 声明一个变量以前使用这个变量,会提示Uncaught ReferenceError: Cannot access 'foo' before initialization
(不该在变量初始化以前使用这个变量)。而若是使用一个未声明的变量,则会提示Uncaught ReferenceError: bar is not defined
ide
console.log(foo);
let foo = 1;
// Uncaught ReferenceError: Cannot access 'foo' before initialization
console.log(bar)
// Uncaught ReferenceError: bar is not defined
复制代码
Let & const 上述的与 var 声明不一样之处带来的另外一个不一样就是:暂时性死区,函数
可是说到暂时性死区,就不得不先提一下块级做用域。ui
在 ES5 中只存在全局做用于和函数做用域(指在函数内声明的全部变量在函数体内始终是可见的,能够在整个函数的范围内使用及复用)。函数做用域会致使一些不合理的地方,这也是面试过程当中会考的一些地方,好比在阮老师的博客中的例子:spa
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
复制代码
而 ES6 新增的块级做用域能够很好的解决这个问题,由于在块级做用域 ({})
声明的变量是在块级做用域的外部取不到的。指针
而函数在块级做用域内的声明遵循下列规则(能够遵照):code
var
,即会提高到全局做用域或函数做用域的头部。一样是阮老师的例子:ip
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
复制代码
而这些又跟暂时性死区又有什么关系呢?
上述所说,块级做用域内声明的变量在此之做用域以外是没法取到的。一样的在内部,
ES6 明确规定,若是区块中存在
let
和const
命令,这个区块对这些命令声明的变量,从一开始就造成了封闭做用域。凡是在声明以前就使用这些变量,就会报错。
这样的状况就能够称之为暂时性死区(TDZ)。
也就是咱们最开始说的在使用 let 关键字声明变量以前声明一个变量会报错:
Uncaught ReferenceError: Cannot access 'aa' before initialization
复制代码
除了这些方面,const 还有其独特的不一样之处:
咱们也知道,const 定义一个常量,常量的值是不能改变的,也意味着声明常量的同时就要给其赋值。其做用域及其表现和 let 相同,也存在TDZ。
可是虽说到如今 const 都很符合咱们的理解,可是 const 所表明的定义的值不能被改变是指变量声明的时候指向的内存地址所保存的数据不得改动[1]。对于基础类型的值,const 声明的变量的值就是内存地址所保存的数据。而对于引用类型的话,const 声明的变量的值就是指向值所在的内存地址的一个指针。const 不能修改的也是这个指针,而指针所表明的内存地址的值能够发生改变。
let const var 三个关键字声明变量的不一样之处有:
from ECMAScript 6 入门 阮一峰 ↩︎