主要知识点:什么是模块、模块中的导出、模块中的导入
![]()
《深刻理解ES6》笔记 目录webpack
模块( Modules )是使用不一样方式加载的 JS 文件(与 JS 原先的脚本加载方式相对)。这种不一样模式颇有必要,由于它与脚本( script )有大大不一样的语义:web
可使用 export 关键字将已发布代码部分公开给其余模块。最简单方法就是将 export放置在任意变量、函数或类声明以前,从模块中将它们公开出去:segmentfault
// 导出数据 export var color = "red"; export let name = "Nicholas"; export const magicNumber = 7; // 导出函数 export function sum(num1, num2) { return num1 + num2; } // 导出类 export class Rectangle { constructor(length, width) { this.length = length; this.width = width; } } // 此函数为模块私有 function subtract(num1, num2) { return num1 - num2; } // 定义一个函数…… function multiply(num1, num2) { return num1 * num2; } // ……稍后将其导出 export { multiply };
注意:数组
一旦你有了包含导出的模块,就能在其余模块内使用 import 关键字来访问已被导出的功能。 import 语句有两个部分,一是须要导入的标识符,二是需导入的标识符的来源模块。
此处是导入语句的基本形式:浏览器
import { identifier1, identifier2 } from "./example.js";
/ 单个导入 import { sum } from "./example.js"; console.log(sum(1, 2)); // 3 //不容许对已导入的绑定从新赋值,因而就会致使错误 sum = 1; // 出错
// 多个导入 import { sum, multiply, magicNumber } from "./example.js"; console.log(sum(1, magicNumber)); // 8 console.log(multiply(1, 2)); // 2
还有一种特殊状况,即容许你将整个模块看成单一对象进行导入,该模块的全部导出都会做为对象的属性存在。例如:ide
// 彻底导入 import * as example from "./example.js"; console.log(example.sum(1, example.magicNumber)); // 8 console.log(example.multiply(1, 2)); // 2
ES6 的 import 语句为变量、函数与类建立了只读绑定,而不像普通变量那样简单引用了原始绑定。尽管导入绑定的模块没法修改绑定的值,但负责导出的模块却能作到这一点。例如,假设你想要使用如下模块:函数
export var name = "Nicholas"; export function setName(newName) { name = newName; }
当你导入了这两个绑定后, setName() 函数还能够改变 name 的值:this
import { name, setName } from "./example.js"; console.log(name); // "Nicholas" setName("Greg"); console.log(name); // "Greg" name = "Nicholas"; // error
function sum(num1, num2) { return num1 + num2; } //将本地名称sum重命名为add export { sum as add };
//将导入名称重命名为sum import { add as sum } from "./example.js"; console.log(typeof add); // "undefined" console.log(sum(1, 2)); // 3
模块的默认值( default value ) 是使用 default 关键字所指定的单个变量、函数或类,而你在每一个模块中只能设置一个默认导出,将 default 关键字用于多个导出会是语法错误。spa
export default function(num1, num2) { return num1 + num2; }
function sum(num1, num2) { return num1 + num2; } export default sum;
function sum(num1, num2) { return num1 + num2; } export { sum as default };
export let color = 'red'; export default function(num1,num2){ return num1+num2; }
import sum from './example.js'; console.log(sum(1,2));
这个导入语句从 example.js 模块导入了其默认值。注意此处并未使用花括号,与以前在非默认的导入中看到的不一样。本地名称 sum 被用于表明目标模块所默认导出的函数。prototype
import sum, { color } from './example.js'; console.log(sum(1,2)); console.log(color);
逗号将默认的本地名称与非默认的名称分隔开,后者仍旧被花括号所包裹。要记住在 import语句中默认名称必须位于非默认名称以前。
// 等价于上个例子 import { default as sum, color } from "example"; console.log(sum(1, 2)); // 3 console.log(color); // "red"
若是在当前模块中对已导入的内容在导出,使用本章已描述过的模式来将已导入的值再导出,就像这样:
import { sum } from "./example.js"; export { sum }
此方法能奏效,但还可使用单个语句来完成相同任务:
export { sum } from "./example.js";
这种形式的 export 会进入指定模块查看 sum 的定义,随后将其导出。固然,你也能够选择将一个值用不一样名称导出:
export { sum as add } from "./example.js";
若你想未来自另外一个模块的全部值彻底导出,可使用星号( * )模式:
export * from "./example.js";
有些模块也许没有进行任何导出,相反只是修改全局做用域的对象。尽管这种模块的顶级变量、函数或类最终并不会自动被加入全局做用域,但这并不意味着该模块没法访问全局做用域。诸如 Array 与 Object 之类的内置对象的共享定义在模块内部是可访问的,而且对于这些对象的修改会反映到其余模块中。
例如,若你想为全部数组添加一个 pushAll() 方法,你能够像下面这样定义一个模块:
// 没有导出与导入的模块 Array.prototype.pushAll = function (items) { // items 必须是一个数组 if (!Array.isArray(items)) { throw new TypeError("Argument must be an array."); } // 使用内置的 push() 与扩展运算符 return this.push(...items); };
这是一个有效的模块,尽管此处没有任何导出与导入。
import "./example.js"; let colors = ["red", "green", "blue"]; let items = []; items.pushAll(colors);
有用过webpack打包js模块的同窗可能有经验,使用webpack打包了多个js文件,而后放到HTML使用script加载时,若是加载顺序不对,就会出现找不到模块的错误。
这是由于模块之间是有依赖关系的,就像你使用jQuery的时候,必须先加载jQuery的代码,才能使用jQuery提供的方法。
加载模块的方法,老是先加载模块1,再加载模块2,由于module类型默认使用defer属性。
<script type="module" src="module1.js"></script> <script type="module" src="module2.js"></script>