1.let命令
基本用法
let和var一样,都是用来声明变量,不同的是let只能是在当前代码块中有效
{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1
从上面代码可以看出在代码块中通过var和let定义变量,var定义的变量可以访问的,let定义的变量直接报错
不存在变量提升
var会有“变量提升”,就是在声明之前使用该变量,值为 undefined 。为了改变这种奇怪现象,let闪亮登场,变量一定要在声明之后使用,否则就会报错:
// var 的情况 console.log(foo); // 输出undefined var foo = 2; // let 的情况 console.log(bar); // 报错ReferenceError let bar = 2;
暂时性死区
只要块级作用域内存在let
命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
上面代码中,存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。
ES6 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。
总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
不允许重复声明
let
不允许在相同作用域内,重复声明同一个变量。
// 报错 function func() { let a = 10; var a = 1; } // 报错 function func() { let a = 10; let a = 1; }
2.块级作用域
ES6 的块级作用域
let
实际上为 JavaScript 新增了块级作用域。
function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }
上面函数有两个作用域,可以看出内层的n=10并没有覆盖外层n,因此输出为外层n的值。
ES6 允许块级作用域的任意嵌套。
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。
块级作用域与函数声明
ES6 规定,块级作用域之中,函数声明语句的行为类似于let
,在块级作用域之外不可引用。
function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }());
上面代码在 ES5 中运行,会得到“I am inside!”,因为在if
内声明的函数f
会被提升到函数头部。
ES6 就完全不一样了,理论上会得到“I am outside!”。但是如果在ES6浏览器中运行就会报错,想了解详细的小伙伴可以点击查看。
3.const命令
基本用法
const声明一个只读常量,一旦声明,常量不可更改,因此声明时必需赋值。
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable.
const
的作用域与let
命令相同: 只在声明所在的块级作用域内有效。
const
声明的常量与let
相同: 变量不提升,同样存在暂时性死区,只能在声明的位置后面使用。
const
声明的常量与let
相同: 不可重复声明。
ES6 声明变量的六种方法
ES5 只有两种声明变量的方法:var
命令和function
命令。
ES6 声明变量方法除了上面两种,还可以通过let和const,还有后面会介绍的import和class,所有ES6有6种声明方式。
4.顶层对象的属性
ES6 一方面规定,var
命令和function
命令声明的全局变量,依旧是顶层对象的属性;
另一方面规定,let
命令、const
命令、class
命令声明的全局变量,不属于顶层对象的属性。
var a = 1; // 如果在 Node 的 REPL 环境,可以写成 global.a // 或者采用通用方法,写成 this.a window.a // 1 let b = 1; window.b // undefined
上面代码中,全局变量a
由var
命令声明,所以它是顶层对象的属性;全局变量b
由let
命令声明,所以它不是顶层对象的属性,返回undefined
。
5.globalThis 对象
JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。
但是很难找到一种方法,可以在所有的情况下都能获取顶层对象,一下方法勉强可以使用:
// 方法一 (typeof window !== 'undefined' ? window : (typeof process === 'object' && typeof require === 'function' && typeof global === 'object') ? global : this); // 方法二 var getGlobal = function () { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); };
ES2020 在语言标准的层面,引入globalThis
作为顶层对象。也就是说,任何环境下,globalThis
都是存在的,都可以从它拿到顶层对象,指向全局环境下的this
。
本节学习到此结束,想了解详细可以点击查看。