我们在使用nodejs时候,经常会用到export、module.exports,我们扪心自问,自己真的了解他们吗?知道内部是怎么实现的吗?
其实不论我们使用他们两个的谁进行导出,其实最后都是调用了 module.exports,这个我们可以通过源码进行窥探,源码中会有这么一步操作,export = module.exports。所以我们在使用export的时候也是能导出的。
那node中为啥还要有export的呢?
node中exports导出的作用:commonJs要求有一个exports作为导出标准,所以node做了妥协,其实node内部帮我们做了赋值操作,module.exports = exports, 所有我们顶上exports.name = ... 才能实现导出功能
ESmodule的导入和导出
导出的三种方式
- 方式一:单个导出
export const name = '张三';
- 方式二:整个导出(这个大括号不是对象,放置的是多个变量引用的列表,不是对象)
export { name, age };
- 方式三:导出时可以给变量设置别名
export { name as FName };
导入的三种方式
- 方式一: 基础导入
import { name, age } from './bar.js'
- 方式二:导出设置别名
import { name as wName, age as wAge } from './bar.js'
- 方式三:全部导出,重设为
import * as foo from './bar.js'
- 方式四:export 和 import 结合使用,从某一个文件中全部导入后,再统一导出,在自己开发组件库或者工具的时候,可以把所有的接口放置到入口中,统一导出
export { name } from './bar.js'
关于 export 和 import 的原理解析
// 原理解析
/*
bar.js
let name = 'why'
let age = 'age'
setTimeout(() => {
name = 'aaaa'
}, 1000);
导出的是name、age的引用,不是对象
export { name, age }
index.js
import { name, age } from './bar.js';
setTimeout(() => {
console.log(name) // 结果是:aaaa
}, 2000)
原理是当js引擎在解析阶段时候,会创建一个 模块环境记录(module environment record)
bindings: 实时绑定
const name = name;
const age = age;
这块绑定的都是引用
所以在index.js中打印的就是最新修改的值 aaaa
反过来测试
index.js
setTimeout(() => {
name = 'cccc'
}, 1000)
bar.js
setTimeout(() => {
console.log(name)
})
报错 TypeError: Assignment to constant variable,所以可以证明js引擎在定义的时候声明为const,所以不能进行反向修改
*/