JavaScript高级程序设计(4)
第26章 模块
### 26.1 理解模块模式 772 ##### 26.1.1 模块标识符 - > 有的模块系统支持明确声明模块的标识,还有的模块系统会隐式地使用文件名作为模块标识符。将模块标识符解析为实际模块的过程要根据模块系统对标识符的实现。 ##### 26.1.2 模块依赖 - > 模块系统的核心是管理依赖。每个模块都会与某个唯一的标识符关联,该标识符可用于检索模块。这个标识符通常是 JavaScript文件的路径。 ##### 26.1.3 模块加载 - > 只有整个依赖图都加载完成,才可以执行入口模块。 ##### 26.1.4 入口 - > 相互依赖的模块必须指定一个模块作为入口(entry point),这也是代码执行的起点。 ##### 26.1.5异步依赖 - > ```javascript > // 在模块 A 里面 > load('moduleB').then(function(moduleB) { > moduleB.doStuff(); > }); > ``` ##### 26.1.6 动态依赖 - > ```javascript > //下面是动态依赖加载的例子: > if (loadCondition) { > require('./moduleA'); > } > ``` ##### 26.1.7 静态分析 ##### 26.18 循环依赖 - > 在包含循环依赖的应用程序中,模块加载顺序可能会出人意料。不过,只要恰当地封装模块,使它们没有副作用,加载顺序就应该不会影响应用程序的运行。 ### 26.2 凑合的模块系统 776 - > 实际开发中并不建议自己动手写模块系统,因为不够可靠。因此必须手动管理依赖和排序。要添加异步加载和循环依赖非常困难。最后,对这样的系统进行静态分析也是个问题。 > > ```javascript > (function() { > // 私有 Foo 模块的代码 > console.log('bar'); > })(); > > //如果把这个模块的返回值赋给一个变量,那么实际上就为模块创建了命名空间: > var Foo = (function() { > console.log('bar'); > })(); > > //为了暴露公共 API,模块 IIFE 会返回一个对象,其属性就是模块命名空间中的公共成员: > var Foo = (function() { > return { > bar: 'baz', > baz: function() { > console.log(this.bar); > } > }; > })(); > > //“泄露模块模式” 只返回一个对象,其属性是私有数据和成员的引用: > var Foo = (function() { > var bar = 'baz'; > var baz = function() { > console.log(bar); > }; > return { > bar: bar, > baz: baz > }; > })(); > ``` ### 26.3 使用ES6之前的模块加载器 779 ##### 26.3.1 CommonJS - > ```javascript > var moduleB = require('./moduleB'); > module.exports = { > stuff: moduleB.doStuff(); > }; > ``` ##### 26.3.2 异步模块定义 - > ```javascript > define('moduleA', ['require', 'exports'], function(require, exports) { > var moduleB = require('moduleB'); > exports.stuff = moduleB.doStuff(); > }); > ``` ##### 26.3.3 通用模块定义 - > ```javascript > (function (root, factory) { > if (typeof define === 'function' && define.amd) { > // AMD。注册为匿名模块 > define(['moduleB'], factory); > } else if (typeof module === 'object' && module.exports) { > // Node。不支持严格 CommonJS > // 但可以在 Node 这样支持 module.exports 的 > // 类 CommonJS 环境下使用 > module.exports = factory(require(' moduleB ')); > } else { > // 浏览器全局上下文(root 是 window) > root.returnExports = factory(root. moduleB); > } > }(this, function (moduleB) { > // 以某种方式使用 moduleB > // 将返回值作为模块的导出 > // 这个例子返回了一个对象 > // 但是模块也可以返回函数作为导出值 > return {}; > })); > ``` ##### 26.3.4 模块加载器终将没落 - > 随着 ECMAScript 6 模块规范得到越来越广泛的支持,本节展示的模式最终会走向没落。 ### 26.4 使用ES6模块 783 ##### 26.4.1 模块标签及定义 - > ```javascript > //下面演示了嵌入模块代码的执行顺序: > <!-- 第二个执行 --> > <script type="module"></script> > <!-- 第三个执行 --> > <script type="module"></script> > <!-- 第一个执行 --> > <script></script> > > //另外,可以改为加载外部 JS 模块定义: > <!-- 第二个执行 --> > <script type="module" src="module.js"></script> > <!-- 第三个执行 --> > <script type="module" src="module.js"></script> > <!-- 第一个执行 --> > <script><script> > > <!-- moduleA 在这个页面上只会被加载一次 --> > <script type="module">import './moduleA.js'<script> > <script type="module">import './moduleA.js'<script> > <script type="module" src="./moduleA.js"></script> > <script type="module" src="./moduleA.js"></script> > ``` ##### 26.4.2 模块加载 - > ECMAScript 6 模块的独特之处在于,既可以通过浏览器原生加载,也可以与第三方加载器和构建工具一起加载。 ##### 26.4.3 模块行为 - > - 模块代码只在加载后执行。 > - 模块只能加载一次。 > - 模块是单例。 > - 模块可以定义公共接口,其他模块可以基于这个公共接口观察和交互。 > - 模块可以请求加载其他模块。 > - 支持循环依赖。 > - ES6 模块默认在严格模式下执行。 > - ES6 模块不共享全局命名空间。 > - 模块顶级 this 的值是 undefined(常规脚本中是 window)。 > - 模块中的 var 声明不会添加到 window 对象。 > - ES6 模块是异步加载和执行的。 ##### 26.4.4 模块导出 - > export 关键字用于声明一个值为命名导出。导出语句必须在模块顶级,不能嵌套在某个块中。 > > ```javascript > // 命名行内导出 > export const baz = 'baz'; > export const foo = 'foo', bar = 'bar'; > export function foo() {} > export function* foo() {} > export class Foo {} > > // 命名子句导出 > export { foo }; > export { foo, bar }; > export { foo as myFoo, bar }; > > // 默认导出 > export default 'foo'; > export default 123; > export default /[a-z]*/; > export default { foo: 'foo' }; > > export { foo, bar as default }; > export default foo > export default function() {} > export default function foo() {} > export default function*() {} > export default class {} > ``` ##### 26.4.5 模块导入 - > 模块可以通过使用 import 关键字使用其他模块导出的值。与 export 类似,import 必须出现在模块的顶级。 > > ```javascript > import { foo, bar, baz as myBaz } from './foo.js'; > import * as Foo from './foo.js'; > > import { default as foo } from './foo.js'; > import foo from './foo.js'; > ``` ##### 26.4.6 模块转移导出 - > 模块导入的值可以直接通过管道转移到导出。此时,也可以将默认导出转换为命名导出,或者相反。如果想把一个模块的所有命名导出集中在一块,可以像下面这样在 bar.js 中使用*导出: > > ```javascript > export * from './foo.js'; > ``` ##### 26.4.7 工作者模块 - >```javascript >// 第二个参数默认为{ type: 'classic' } >const scriptWorker = new Worker('scriptWorker.js'); >const moduleWorker = new Worker('moduleWorker.js', { type: 'module' }); >``` ##### 26.4.8 向后兼容 - > ```javascript > // 支持模块的浏览器会执行这段脚本 > // 不支持模块的浏览器不会执行这段脚本 > <script type="module" src="module.js"></script> > > // 支持模块的浏览器不会执行这段脚本 > // 不支持模块的浏览器会执行这段脚本 > <script nomodule src="script.js"></script> > ```
顶部
收展
底部
[TOC]
目录
第1章 JavaScript简介
第2章 在 HTML中使用JavaScript
第3章 语言基础(1)语法变量
第3章 语言基础(2)数据类型
第3章 语言基础(3)操作符
第3章 语言基础(4)语句
第4章 变量、作用域与内存
第5章 基本引用类型
第6章 集合引用类型
第7章 迭代器与生成器
第8 章对象、类与面向对象编程
第9章 代理与反射
第10章 函数
第11章 期约与异步函数
第12章 BOM
第13章 客户端检测
第14章 DOM
第15章 DOM 扩展
第16章 DOM2 和 DOM3
第17章 事件
第18章 动画与 Canvas 图形
第19章 表单脚本
第20章 JavaScript API
第21章 错误处理与调试
第22章 处理 XML
第23章 JSON
第24章 网络请求与远程资源
第25章 客户端存储
第26章 模块
第27章 工作者线程
第28章 最佳实践
相关推荐
WebSocket