let 命令
let 用于声明变量,用法和 var 类似,但是所声明的变量仅在 let 所在的代码块内有效
var 命令会发生变量提升现象,即变量可以在声明之前使用,值为 undefined
let 命令改变了语法行为,它所声明的变量一定要在声明之后使用,否则会报错
在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这个语法称之为「暂时性死区」(TDZ)
暂时性死区的本质就是,只要进入当前作用域,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量
let 不允许在相同作用域内重复声明同一个变量
块级作用域
ES5 只有全局作用域和函数作用域,没有块级作用域
let 的使用,为 JavaScript 新增了块级作用域
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明
// 情况一
if(true) {
function f() {}
}
// 情况二
try {
function f() {}
} catch (e) {}
上面两种函数声明在 ES5 下都是非法的,但是浏览器没有遵守这个规定,还是支持在块级作用域下声明函数,因此不会报错
ES6 引入块级作用域之后,明确允许在块级作用域之中声明函数。ES6 规定,在块级作用域之中,函数声明语句的行为类似 let ,在块级作用域之外不可引用
function f() { console.log('I an outside!') }
(function () {
if (false) {
function f() { console.log('I am inside!') }
}
f()
}())
以上代码在 ES5 中运行会得到 「I am outside」,因为 f 会被提升到函数头部
在 ES6 中,理论上会得到 「I an inside」。但是在 ES6 浏览器中会报错
因为浏览器的实现可以不遵守上面的规定,而有自己的行为方式
- 允许在块级作用域内声明函数
- 函数声明类似于 var ,即会提升到全局作用域或函数作用域的头部
- 同时,函数声明还会提升到所在的块级作用域的头部
现在有一个提案,使得块级作用域变成表达式,即可以返回值,办法就是在块级作用域之前加上 do ,使它变成 do 表达式
let x = do {
let t = f()
t * t + 1
}
const 命令
const 声明一个只读的常量。一旦声明,常量的值就不能改变
const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动
ES5 只有两种声明变量的方法,使用 var 和 function 命令
ES6 除了添加了 let 和 const 命令,还有两种声明变量的方法:使用 import 和 class 命令
所以 ES6 一共有 6 种声明变量的方法
顶层对象的属性
顶层对象在浏览器中指的是 window 对象,在 Node 中指的是 global 对象,在 ES5 中,顶层对象的属性 和 全局变量是等价的
ES6 为了保持兼容,var 命令 和 function 命令声明的全局变量依旧是顶层对象的属性,另一方面,let、const 和 class 声明的全局变量不再属于顶层对象的属性,也就是说,从 ES6 开始,全局变量和顶层对象的属性将逐步隔离
var a = 1
window.a // 1
let b = 1
window.b // undefined