ES6读书简记·let & const

CY 2019年01月02日 99次浏览

最近有点时间,于是就想加强我对ES6的认知,找到了阮老师的《ECMAScript 6 入门》读一下,顺便做一下简记,简记的目的是用最简单的语言来概括出尽量全面的知识点,如果书上的某些话好懂,就直接摘下来,如果难懂的话,尽量结合自己的理解用自己的语言来表达清楚,这样,如果以后需要复习的话,直接看简记就可以了,这样比看书效率高一点,毕竟全是知识点的描述。

ECMAScript 6 简介

ECMAScriptJavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 JScriptActionScript)。日常场合,这两个词是可以互换的。

2015 年 6 月正式发布了ES6

之后的每年的 6 月份正式发布一次,作为当年的正式版本。

ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015ES2016ES2017 等等 。

在线将 ES6 代码转为 ES5 代码

let 和 const 命令

基本规则

let声明的变量只在它所在的代码块有效

for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

不存在变量提升

let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错,let不存在变量提升

暂时性死区

ES6明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。 语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ) 。

“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。 只要处于暂时性死区的变量, typeof运行时就会抛出一个ReferenceError,不使用let的时候未声明的变量还可以使用typeof,如果使用了let,在let声明变量之前使用typeof操作这个变量,就会抛异常的。

暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

不允许重复声明

let不允许在相同作用域内,重复声明同一个变量 。

块级作用域

let实际上为 JavaScript 新增了块级作用域解决了变量泄露的问题,这样就可以不用IIFE写法了。

// IIFE 写法
(function () {
  var tmp = ...;
  ...
}());

// 块级作用域写法
{
  let tmp = ...;
  ...
}

块级作用域声明函数

ES6引入了块级作用域,明确允许在块级作用域之中声明函数。 ES6规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

以下规则只对 ES6 的浏览器实现有效:

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

因为环境的差异,所以避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

ES6块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域 。

// 第一种写法,报错
if (true) let x = 1;

// 第二种写法,不报错
if (true) {
  let x = 1;
}

严格模式下,函数只能声明在当前作用域的顶层。

这里的记录太简略,详情查看

const 命令

const声明一个只读的常量。一旦声明,常量的值就不能改变 ,const一旦声明变量,就必须立即初始化 。

const的作用域与let命令相同:只在声明所在的块级作用域内有效 。

const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

const声明的常量,也与let一样不可重复声明。

const声明变量的本质是,变量的内存地址将不能改变,不是变量内部的值不能改变,这意味着可以改变声明为常量的数组和对象里面的值。

如果要彻底的冻结一个对象,使其完全不能改变,使用下面的方式:

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

ES6 声明变量的六种方法【考点?】

var命令、function命令、letconst命令、import命令、class命令

顶层对象的属性

在浏览器中的顶层对象为window对象, 从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩 , var命令和function命令声明的全局变量,依旧是顶层对象的属性 , let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。

globalThis对象

因为各种环境下的顶层对象都不一样,所以为了统一顶层对象,引入了globalThis对象

  • 浏览器里面,顶层对象是window,但 NodeWeb Worker 没有window
  • 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self
  • Node 里面,顶层对象是global,但其他环境都不支持。

任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指向全局环境下的this