1.let命令
(1)只在let命令所在的代码块内有效。另外,for循环还有这样一个特别支持,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
var i = 'abc'; // 用let声明会报错参数作用域会带入函数体,所以参数已经声明的变量,函数体内不得用let再次声明
console.log(i);
}
// abc
// abc
// abc
(2)变量不存在提升,一定要先声明再使用,不然会报错。在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
(3)不允许在相同作用域内,重复声明同一个变量。
2.块级作用域
(1)存在原因: 1.内层变量覆盖外层的 2.循环变量泄露为全局变量。
(2)let新增了块级作用域,块级作用域的出现,匿名立即执行函数表达式不再必要了。
(3)块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
3.const命令
(1)声明一个只读的常量。一旦声明,常量的值就不能改变。
const的作用域与let命令相同:只在声明所在的块级作用域内有效。
同样存在暂时性死区,只能在声明的位置后面使用。
const声明的常量,也与let一样不可重复声明。
(2)const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
4.顶层对象的属性
(1)顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。
(2) var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined
5.globalThis 对象
(1)全局环境中,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefind。
(2)函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefind。