module.exports、exports、export有什么
一、module.exports、exports、export有什么区别?
image.png这三个东西其实是两个概念的区分: 先来看一个表格:
这样看其实还是挺清晰的,不同规范使用的关键词和特性不同而已,我们在使用这些关键词的时候区分自己是什么环境下写的代码。
- nodejs(webpack,babel)->commonjs,
- 浏览器(
vue
的script
标签 或html
中带type="module"
的script
标签中)->esm
。
module.exports、exports
是一伙的,他们都是基于commonjs
规范来的。export
是基于es6
的esm(ECMA Script Modules)
规范来的。
二、commonjs规范:
CommonJS
规范是为了解决JavaScript
的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。该规范的主要内容是,模块必须通过module.exports
导出对外的变量或接口,通过require()
来导入其他模块的输出到当前模块作用域中。
2.1. 列子:
// moduleA.js
module.exports.double = function( value ){
return value * 2;
}
// moduleB.js
var { double } = require('./moduleA');
var res = double(4);
console.log(res) //8
为了方便,某些情况下·module.exports·可以简写为·exports·。其实一开始
exports
就是module.exports
的引用。
module.exports===exports //true
所以上面的
moduleA.js
,可以这样省略掉module
// moduleA.js
exports.double = function (value) {
return value * 2;
}
// moduleB.js
var { double } = require('./moduleA');
var res = double(4);
console.log(res) //8
2.2. 注意
当 module.exports后面跟着赋值语句时,不能省略module.,为什么?我们接着看
一开始 module.exports全等于 exports 我们可以看成在文件开头有这样的代码:
module.exports = {};//方便理解 一开始是空对象
let exports = module.exports;
console.log(module.exports===exports)//true
所以在
exports
对象{}
上添加任何的新属性,其实就是在module.exports
上添加属性,因为我们知道node
中对象也是引用类型的。
exports.double = function (value) {
return value * 2;
}
exports.PAI = 3.1415926535897932384626 //233,我可以背这么多位~
exports.add = function (a, b) {
return a + b;
}
危!直接给exports赋值就不行了
module.exports = {};//方便理解 一开始是空对象
let exports = module.exports;
//给exports 赋值会切断和 module.exports 的联系
//这样 不要这样做~!
exports = {
name: 'zhangsan'
}
//或这样 不要这样做~!
exports = function name(a) {}
//或这样 不要这样做~!
exports = 3.1415926535897932384626
console.log(module.exports); // 打印:{} 回到初始{}值
console.log(exports); // 打印:3.1415926535897932384626
console.log(module.exports === exports); //false 你走的独木桥 我走我的阳关道 已经莫得关系了
如果要使用赋值来导出,可以这样导出一个对象:
// moduleA.js
module.exports = {
name:'法外狂徒张三',
age:'19',
wife:'隔壁小红'
}
// moduleB.js
let { name, wife } = require('./moduleA');
console.log(name,age) //法外狂徒张三 隔壁小红
这样
module.exports
就能保证获取到值。
2.4. 如何重命名
commonjs中重命名导出的变量用(
:
)符号:
let { name, wife: girlfriend } = require('./moduleA');
三、esm(ECMA Script Modules)规范
现在来说我们在编写
vue
或者react
项目中熟悉的es6 module
规范。
esm
是将javascript
程序拆分成多个单独模块,并能按需导入的标准。和webpack,babel
不同的是,esm
是javascript
的标准功能,在浏览器端和nodejs
中都已得到实现。使用esm
的好处是浏览器可以最优化加载模块,比使用库更有效率。通过import, export
语法实现模块变量的导入和导出
划重点:commonjs
中使用require
和modelue.exports
实现模块的导入导出,esm
使用import, export
导入导出。
3.1. export
esm
的export
支持:let、var、const、function、class
等 以下都是正确的导出方式:
var person = {
name: '猫小白',
text: a,
}
export {
person,
}
export function showAge() {
console.log(person.age);
}
export let city = '成都'
export const PAI = '3.141592653'
注意:export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
// 错误1
export 3.14;
这种写法都是错误的,因为
export
后面直接跟了一个具体的,外部无法通过一个特定的标识(变量)来获取这个值。
export导出的数据如何重命名?
import { wife as girlfrend } from "./moduleA.js";
想要导出所有方法或变量为指定的一个变量时,可以用 import * as mod from "xxxx"
import * as tool from "./moduleA.js";
console.log(tool.API) //3.141592
3.2. export default 默认导出
和
commonjs
规范先进一点的是esm
提供了一种默认导出的方式。export default
后面可以直接跟随:变量、具体值、function、calss。
//正确
let a = '张三';
export default a
//正确
export default 3.14
export default function (a) {
return a * a
}
//正确
let sum = function (a, b) {
return a + b
}
export default sum
//正确
function calc(a, b) {
return a + b
}
export default calc
3.3. ESM模块规范规定,在html中 script标签设置type='module'可以书写ESM模块代码,包括导入功能:
<script type="module">
import { name,wife } from "./es6/moduleA.js"
console.log(name,wife); //法外狂徒张三 小红
//...其它代码
</script>