深入理解 ES6 #13-用模块封装代码

什么是模块

模块是自动运行在严格模式下并且没有办法退出运行的 JavaScript 代码。

在模块顶部创建的变量不会自动被添加到全局变量作用域,这个变量仅在模块的顶级作用域中存在,而且模块必须导出一些外部代码可以访问的元素。

模块也可以从其他模块导入绑定。

在模块的顶部,this 的值是 undefined

模块不支持 HTML 风格的代码注释。

导出的基本语法

export 关键字将一部分已发布的代码暴露给其它模块。

深入理解 ES6 #12-代理(Proxy)和反射(Reflection)API

代理(Proxy)是一种可以拦截并改变底层 JavaScript 引擎操作的包装器,在新语言中通过它暴露内部运作的对象,从而让开发者可以创建内建的对象。

数组问题

在 ECMAScript6 出现之前,开发者不能通过自己定义的对象模仿 JavaScript 数组对象的行为方式。当给数组的特定元素赋值时,影响到该数组的 length 属性,也可以通过 length 属性修改数组元素。

let colors = ["red", "green", "blue"];

console.log(colors.length); // 3

colors[3] = "black";

console.log(colors.length); // 4
console.log(colors[3]); // "black"

colors.length = 2;

console.log(colors.length); // 2
console.log(colors[3]); // undefined
console.log(colors[2]); // undefined
console.log(colors[1]); // "green"
深入理解 ES6 #2-字符串和正则表达式

更好的 Unicode 支持

在 ES6 出现以前,JS 字符串一直基于 16 位字符编码(UTF-16)进行构建。

每 16 位的序列是一个编码单元(code unit),代表一个字符。

lengthcharAt() 等字符串属性和方法都是基于这种编码单元构造的。

Unicode 引入扩展字符集后,16 位的序列不足以表示所有的字符,编码规则不得不进行改变。

UTF-16 码位(code point)

在 UTF-16 中,前 2162^{16} 个码位均以 16 位的编码单元表示,这个范围被称作基本多文种平面(BMP,Basic Multilingual Plane)

深入理解 ES6 #1-块级作用域绑定

var 声明及变量提升(Hoisting)机制

在函数作用域或全局作用域中通过 var 关键字声明的变量,无论实际上是在哪里声明的,都会被当成在当前作用域顶部声明的变量。

这就是我们常说的提升(Hoisting)机制

通过下面的 getValue 函数来说明:

function getValue(condition) {
  if (condition) {
    var value = "blue";
    console.log(value); // blue
  } else {
    console.log(value); // undefined
  }
  
  console.log(value); // 再次打印 value 的值
  return value;
}
深入理解 ES6 #11-Promise 与异步编程

异步编程的背景知识

JavaScript 引擎是基于单线程(Single-threaded)实际循环的概念构建的,同一时刻只允许一个代码块在执行。

所以需要跟踪即将运行的代码,那些代码被放在一个任务队列(job queue)中,每当一段代码准备执行时,都会被添加到任务队列。每当 JavaScript 引擎中的一段代码结束执行,事件循环(event loop)会执行队列中的下一个任务,它是 JavaScript 引擎中的一段程序,负责监控代码执行并管理任务队列。队列中的任务会从第一个一直执行到最后一个。

深入理解 ES6 #10-改进的数组功能

创建数组

在 ES6 之前,创建数组的方式主要有两种:

  • 调用 Array 构造函数
  • 用数组字面量语法

为了简化数组的创建过程,ES6 新增了两个方法:

  • Array.of()
  • Array.from()

Array.of() 方法

ES6 之所以向 JS 添加新的数组创建方法,是要帮助开发者们规避通过 Array 构造函数创建数组时的怪异行为。

let items = new Array(2);
console.log(items.length); // 2
console.log(items[0]);
console.log(items[1]);

items = new Array("2");
console.log(items.length); // 1
console.log(items[0]); // "2"

items = new Array(1, 2);
console.log(items.length); // 2
console.log(items[0]); // 1
console.log(items[1]); // 2

items = new Array(3, "2");
console.log(items.length); // 2
console.log(items[0]); // 3
console.log(items[1]); // "2"
深入理解 ES6 #9-JavaScript 中的类

大多数面向对象的编程语言都支持类和类继承的特性,而 JavaScript 却不支持这些特性,只能通过其他方法定义并关联多个相似的对象。这个状态一直从 ECMAScript 1 持续到 ECMAScript 5。

尽管一部分 JavaScript 开发强烈坚持 JavaScript 中不需要类,但由于类似的库层出不穷,最终还是在 ECMAScript 6 中引入了类的特性。

ECMAScript 6 中的类与其他语言中的还是不太一样,其语法的设计实际上借鉴了 JavaScript 的动态性

ECMAScript 5 中的近类结构

首先创建一个构造函数,然后定义另一个方法并赋值给构造函数的原型。

深入理解 ES6 #8-迭代器(Iterator)和生成器(Generator)

循环语句的问题

var colors = ["red", "green", "blue"];
for (var i = 0, len = colors.length; i < len; i++) {
    console.log(colors[i]);
}
深入理解 ES6 #7-Set 集合和 Map 集合

ES6 新标准中将 Set 集合和 Map 集合添加到 JS 中。

ES5 中 Set 集合和 Map 集合

在 ES5 中,开发者们用对象属性来模拟这两种集合。

var set = Object.create(null);

set.foo = true;

// 检查属性是否存在
if (set.foo) {
    // ...
}
深入理解 ES6 #6-Symbol 和 Symbol 属性

在 ES5 及早期版本中,JS 语言包含 5 中原始类型:

  • 字符串型
  • 数字型
  • 布尔型
  • null
  • undefined

ES6 引入了第六种原始类型:

  • Symbol

创建 Symbol

let firstName = Symbol();
let person = {};
person[firstName] = "JiaJia";
console.log(person[firstName]); // "JiaJia"
深入理解 ES6 #5-解构:使数据访问更便捷

ES6 为对象和数组都添加了解构功能,将数据解构打散的过程变得更简单,可以从打散后更小的部分中获取所需信息。

对象解构

let node = {
    type: "Identifier",
    name: "foo"
};

let {type, name} = node;

console.log(type); // "Identifier"
console.log(name); // "foo"
深入理解 ES6 #4-扩展对象的功能性

对象类别

ES6 规范清晰定义了每一个类别的对象。

  • 普通(Ordinary)对象

    具有 JS 对象所有的默认内部行为

  • 特异(Exotic)对象

    具有某些与默认行为不符的内部行为

  • 标准(Standard)对象

    ES6 规范中定义的对象,例如 Array,Date 等。标准对象既可以是普通对象,也可以是特异对象。

  • 内建对象

    脚本开始执行时存在于 JS 执行环境中的对象,所有标准对象都是内建对象。

深入理解 ES6 #3-函数

函数形参的默认值

ES6 中的默认参数值

function makeRequest(url, timeout = 2000, callback = function() {}) {

}