每天一点点之ES6学习 - let和const命令

1.let命令

基本用法

letvar一样,都是用来声明变量,不同的是let只能是在当前代码块中有效

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

从上面代码可以看出在代码块中通过varlet定义变量,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 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。

总之,在代码块内,使用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 声明变量方法除了上面两种,还可以通过letconst,还有后面会介绍的importclass,所有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

上面代码中,全局变量avar命令声明,所以它是顶层对象的属性;全局变量blet命令声明,所以它不是顶层对象的属性,返回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

 

 

本节学习到此结束,想了解详细可以点击查看

 

posted @ 2020-08-20 17:35  我若亦如风  阅读(223)  评论(0编辑  收藏  举报