什么是模块
模块是自动运行在严格模式下并且没有办法退出运行的 JavaScript 代码。
在模块顶部创建的变量不会自动被添加到全局变量作用域,这个变量仅在模块的顶级作用域中存在,而且模块必须导出一些外部代码可以访问的元素。
模块也可以从其他模块导入绑定。
在模块的顶部,this
的值是 undefined
。
模块不支持 HTML 风格的代码注释。
导出的基本语法
用 export
关键字将一部分已发布的代码暴露给其它模块。
模块是自动运行在严格模式下并且没有办法退出运行的 JavaScript 代码。
在模块顶部创建的变量不会自动被添加到全局变量作用域,这个变量仅在模块的顶级作用域中存在,而且模块必须导出一些外部代码可以访问的元素。
模块也可以从其他模块导入绑定。
在模块的顶部,this
的值是 undefined
。
模块不支持 HTML 风格的代码注释。
用 export
关键字将一部分已发布的代码暴露给其它模块。
代理(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 出现以前,JS 字符串一直基于 16 位字符编码(UTF-16)进行构建。
每 16 位的序列是一个编码单元(code unit),代表一个字符。
length
、charAt()
等字符串属性和方法都是基于这种编码单元构造的。
Unicode 引入扩展字符集后,16 位的序列不足以表示所有的字符,编码规则不得不进行改变。
在 UTF-16 中,前 216 个码位均以 16 位的编码单元表示,这个范围被称作基本多文种平面(BMP,Basic Multilingual Plane)。
在函数作用域或全局作用域中通过 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;
}
JavaScript 引擎是基于单线程(Single-threaded)实际循环的概念构建的,同一时刻只允许一个代码块在执行。
所以需要跟踪即将运行的代码,那些代码被放在一个任务队列(job queue)中,每当一段代码准备执行时,都会被添加到任务队列。每当 JavaScript 引擎中的一段代码结束执行,事件循环(event loop)会执行队列中的下一个任务,它是 JavaScript 引擎中的一段程序,负责监控代码执行并管理任务队列。队列中的任务会从第一个一直执行到最后一个。
在 ES6 之前,创建数组的方式主要有两种:
为了简化数组的创建过程,ES6 新增了两个方法:
Array.of()
Array.from()
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"
大多数面向对象的编程语言都支持类和类继承的特性,而 JavaScript 却不支持这些特性,只能通过其他方法定义并关联多个相似的对象。这个状态一直从 ECMAScript 1 持续到 ECMAScript 5。
尽管一部分 JavaScript 开发强烈坚持 JavaScript 中不需要类,但由于类似的库层出不穷,最终还是在 ECMAScript 6 中引入了类的特性。
ECMAScript 6 中的类与其他语言中的还是不太一样,其语法的设计实际上借鉴了 JavaScript 的动态性
首先创建一个构造函数,然后定义另一个方法并赋值给构造函数的原型。
var colors = ["red", "green", "blue"];
for (var i = 0, len = colors.length; i < len; i++) {
console.log(colors[i]);
}
ES6 新标准中将 Set
集合和 Map
集合添加到 JS 中。
在 ES5 中,开发者们用对象属性来模拟这两种集合。
var set = Object.create(null);
set.foo = true;
// 检查属性是否存在
if (set.foo) {
// ...
}
在 ES5 及早期版本中,JS 语言包含 5 中原始类型:
null
undefined
ES6 引入了第六种原始类型:
Symbol
let firstName = Symbol();
let person = {};
person[firstName] = "JiaJia";
console.log(person[firstName]); // "JiaJia"
ES6 为对象和数组都添加了解构功能,将数据解构打散的过程变得更简单,可以从打散后更小的部分中获取所需信息。
let node = {
type: "Identifier",
name: "foo"
};
let {type, name} = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
ES6 规范清晰定义了每一个类别的对象。
普通(Ordinary)对象
具有 JS 对象所有的默认内部行为
特异(Exotic)对象
具有某些与默认行为不符的内部行为
标准(Standard)对象
ES6 规范中定义的对象,例如 Array,Date 等。标准对象既可以是普通对象,也可以是特异对象。
内建对象
脚本开始执行时存在于 JS 执行环境中的对象,所有标准对象都是内建对象。
function makeRequest(url, timeout = 2000, callback = function() {}) {
}