传统模块化方式的问题
<body>
<script src="./index.js"></script>
<script src="./home.js"></script>
<script src="./list.js"></script>
</body>
传统通过script标签引入模块的方式的问题:
- 全局污染:没有块级作用域,会导致污染变全局量;
- 依赖管理混乱:正常来说,引入的模块会被按引入顺序依次执行,模块间存在相互依赖的关系时,变得难以管理
Commonjs
使用:
导出:
// Commonjs到处相当于导出的是一个 exports 对象
exports.sex = 'male'
exports.name = 'Pike'
module.exports ={
name:'alien', // 之前定义的name属性在这里被覆盖
author:'青空',
say(){
console.log(666)
}
}
导入:
const a = require('./a')
特性
-
CommonJS 模块由 JS 运行时实现。
-
CommonJs 是单个值导出,本质上导出的就是 exports 属性。
-
CommonJS 是可以动态加载的,对每一个加载完成的文件进行标记,进行缓存,当再次导入时无需重新加载,直接从缓存获取结果,可以有效的解决循环引用问题。
-
CommonJS 模块同步加载并执行模块文件,顺序执行,动态加载。
Es Module
使用
导出:
// Es Module导出一个对象,其中默认导出的内容存在default属性中,其余导出自动生成一个属性
export const name = 'Pike' // 在导出的对象中添加一个名为"name"的属性
export const author = '青空' // 同上
export default function say (){
console.log('hello , world!')
} // 默认到处只能有一个,此时default属性即该函数
导入:
import theSay , // 默认导出需要命名
{ name, author as bookAuthor } from './a.js'
重命名导出:
export { name as bookName , author ,
default as say // 重命名默认导出的default
} from 'module' //第三种方式
特性
-
ES6 module 的引入和导出是静态的,因此
import,export不能放在块级作用域或条件语句中,这有利于代码在打包过程中查找依赖,进行tree shaking -
import 的导入名不能为字符串或在判断语句
-
import会自动提升到代码的顶层,相当于定义变量,因此会提前加载,与Common.js相同,对于相同的js文件会进行标记及缓存 -
import导入的变量时只读的,无法修改,相当于一个单例模式 -
import()方法动态引入,返回一个
Promise对象, 返回的Promise的 then 成功回调中,可以获取模块的加载成功信息。需要在 webpack 中做相应的配置处理才能支持这种方式。setTimeout(() => { const result = import('./b') result.then(res=>{ console.log(res) }) }, 0); -
ES6 Module 导入模块在严格模式下。