一、模块化的理解
1.什么是模块?
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信
2.模块化的好处
- 避免命名冲突(减少命名空间污染)
- 更好的分离, 按需加载
- 更高复用性
- 高可维护性
二、模块化规范
模块化规范有CommonJS、AMD、CMD、ES6模块化
这篇文章主要对CommonJS和ES6模块化进行一个汇总整理(在nodejs上运行 : node init初始化文件)
运行ES6模块时,需要在package.json文件中添加"type":"module",并且在引入时路径中不能省略文件后缀名;
运行CommonJS时,需要在package.json文件中添加"type":"commonjs",在引入路径时可以省略文件后缀名
1.ES6模块化(静态加载,编译时加载)
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
ES6模块化语法
export命令用于规定模块的对外接口,即模块的暴露
import命令用于输入其他模块提供的功能,即模块的导入。
①单个属性的导出、导入
//单个属性的导出 文件名为 a.js
export let a = 1;
export function count(){
console.log(++a);
}//引用 文件名为 index.js
import {a,count} from './a.js'
console.log(a) // 1
count() // 2
②列表和重命名的导出、导入
//暴露模块 文件名 a.js
let firstName = "zhang"
let lastName = "xiaoxiao"
//列表导出
export {firstName , lastName}
//重命名导出
export { firstName as first, lastName as last}
//引入模块 文件名 index.js
//列表引入
import { firstName , lastName } from "./a.js";
console.log("列表"+firstName,lastName); //列表zhang xiaoxiao
//重命名引入
import { first , last } from "./a.js";
console.log("重命名"+first,last); //重命名zhang xiaoxiao
③默认导出 export default function foo(){ }; / export default {}
使用import命令的时候,我们需要知道所要加载的变量名或函数名,否则无法加载。为了方便,能使我们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。
模块内部的默认导出,有且只能有一个
//文件名 a.js 模块暴露
export default function foo(){
console.log("default 默认导出");
}
//文件名 index.js 引入默认导出的模块
import fun from "./a.js"
fun() // default 默认导出
//这里的fun并不是固定的,我们可以给任意的变量名来接收这个模块
④导入所有模块 import * as obj(自定义) from '路径'
//文件名 index.js
import * as obj from '.a.js'; //as 后面obj 也是可以自定义的变量名来接收
console.log(obj);
//打印结果 [Module: null prototype] {
a: 1,
count: [Function: count],
default: [Function: default],
first: 'zhang',
firstName: 'zhang',
last: 'xiaoxiao',
lastName: 'xiaoxiao'
}⑤ 运行模块 类似于script标签的导入形式
//文件名 index.js
import "./a.js" //可以运行a.js中的js代码
另外,①-④的引入也可以运行目标文件中的js代码(console.log()等都可以运行),并且,当在运行index文件时,console.log()命令先被打印。
2.CommonJS(运行时加载)
//导出 文件名 b.js
let a =1;
let add =()=>{
++a
}
module.exports = {
a,
add
}
//导入 文件名 index.js 要运用 require() 命令
let obj = require('./modules/b')
console.log(obj);
//对象的解构形式
let {a,add} = require('./modules/b')
console.log(a,add);
三、ES6 模块与 CommonJS 模块的差异
它们有两个重大差异:
① CommonJS 模块输出的是一个值的拷贝(理解起来类似于值传递),ES6 模块输出的是值的引用(理解起来类似于引用传递)。
② CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。