模块化表格对比

模块规范 导出命令 导入命令 静态还是动态 值是否被缓存 是否采用严格模式 加载是否是同步的 适应端 顶层this指向哪里
es6 module export import 静态 值的引用,不会缓存,运行时再根据引用去取值 浏览器和服务端 undefined
commonjs module.exports require 动态,运行时加载 会缓存 同步 服务端 指向当前模块
AMD规范 return或者兼容commonjs的 异步 浏览器

一、es6 module:浏览器和服务器通用的模块解决方案

1、静态化。编译时就能确定模块的依赖关系;commonjs和AMD只能在运行时确定。

优点:

  • 不在需要UMD模块格式了。
  • 不再需要对象作为命名空间。
  • 将来浏览器新的API就能用模块格式提供,不在必须做成全局变量或者navigator对象的属性。

2、es6模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。缺点:没法引用es6模块本身,因为它不是对象。

3、自动采用严格模式,所以严格模式的规则,es6模块要遵守。

4、导入和导出:import和export。

  1. 都可以使用as别名。export语句输出的接口,与其对应的值是动态绑定的。
  2. 可以出现在模块顶层的任何位置,不能处于块级作用域内,否则会报错。因为这样就没法做静态优化了。
  3. import命令输入的变量都是只读的。不允许在加载模块的脚本里面改写接口。以下情况要注意:
import { a } from './xxx.js';
a = {}; // 报错,a是只读的

a.foo = 'hello'; // 不报错。但是其他模块也可以读到改写后的值,引起bug,所以不能这么操作。
  1. import命令有提升效果,会提升到整个的头部。本质:import是静态的,在编译阶段执行,所以import也不能使用表达式或者变量表示。
  2. import会执行所加载的模块,不可省略模块后缀名。
import './test.js'; // 会直接加载并执行test.js的代码。
  1. 尽量不要把require和import在一个文件里混用。在一起用的话会先执行import的。

5、es6module可以继承

// circleplus.js

export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
  return Math.exp(x);
}

二、commonJs:服务端模块化规范。

1、加载机制:输入的是被输出值的拷贝。一旦输出,模块内部变化就影响不到这个值。

2、所有代码都运行在模块作用域。

3、模块可以多次加载,但只在第一次加载时运行一次,其结果会被缓存。后面再加载的时候,就直接读取缓存结果。要想让模块再运行的话,必须清除缓存。(delete require.cache[moduleName])

4、模块加载的顺序,按照其在代码中出现的顺序。

5、module对象:

  • module.id:模块的标识符,通常是带有绝对路径的模块文件名。
  • module.filename: 模块的文件名,带有绝对路径。
  • module.loaded:模块是否已经加载完成。
  • module.parents:[],调用该模块的模块。node下执行,会得到null或者undefined,require引入的会返回它的调用模块。可以用此判断该模块是不是入口模块。
  • module.exports:表示模块对外输出的值。还有个exports变量,指向的是module.exports。不能直接将 exports 变量指向一个值,因为这样等于切断了 exports 与 module.exports 的联系。

6、require:用于加载模块文件。

  1. 步骤:读入并执行一个js文件,返回该模块的exports对象。若没有发现指定模块则报错。
  2. 加载规则:加载文件的后缀默认是.js。
require参数 加载规则
'/'开头 加载的是绝对路径的文件
'./'开头 加载的是相对路径的文件
不以/或者./开头 默认提供的核心模块(位于Node的系统安装目录中)或者一个位于各级node_modules目录的已安装模块
不以/或./开头,是一个路径 先找第一级的位置,再依次往后续找

指定的模块没发现的话,node会尝试为文件名添加.js,.json,.node后缀来找。

  1. require.resolve可以拿到require命令加载的确切文件名。

7、输出的是值的缓存。

三、UMD(Universal Module Definition)希望提供一个前后端跨平台的解决方案。

  • 以此判断是否支持Nodejs模块格式:(typeof exports === 'object'),是否支持AMD(typeof define === 'function'),都不支持则将模块公开到全局(window或global)。

雨花石
410 声望19 粉丝

人生没有彩排,每天都是直播