commonjs & ES module 模块化
浅聊一下
记得刚入前端那会,总听大家说 commonjs
和 ES module
模块化开发,但一直没明白他们之间到底有个什么羁绊,nodejs的模块化规范包括 commonjs规范
和 ES module规范
,借着对 node.js
学习的开始,来聊一聊commonjs
和 ES module
...
在金三银四的尾巴上了车,如果你也和我一样也想在大三找一份还不错的实习,欢迎掘友们私聊我交流面经(wechat: LongLBond)
commonjs
使用commonjs规范
第一步我们需要明白如何使用commonjs规范,首先使用npm init
初始化我们的项目,初始完毕以后,在我们的目录中会多出一个package.json
文件,添加一个type
,type
的值可以修改为commonjs
和 module
分别对应commonjs规范
和 ES module规范
npm init
commonjs引入和导出模块
- 导出模块
我们要想文件中引入其他文件中的方法或属性,就得先在其他的文件中将方法和属性导出,那么在文件中如何来导出方法和属性?
// 导出对象
module.exports = {
success:1,
error:0,
fn: {}
}
// 导出值
module.exports = 12345
- 引入模块
- 引入自己编写的模块
刚才我们在文件中已经使用了module.exports
来抛出一个模块,那么我们如何引入?
const obj = require('./test.js')
console.log(obj);
看看结果
- 引入第三方模块
在开发过程中我们时常需要引入一些第三方的模块
const md5 = require('md5')
- 引入nodejs内置模块
fs http net os child_process
const fs = require('node:fs') // 高版本nodejs node:fs 低版本 fs
- 引入C++扩展 addon napi node-gyp .node
- 引入json文件
const data = require('./data.json')
ES module
- 导出模块
可以选择以下方式导出模块
// 导出变量
export const name = 'bd'
// 导出对象
export default {
success:1,
error:0,
fn: {}
}
- 导入模块
import obj from './test.js'
需要注意的是,ES module 规范不支持引入json文件。但是如果非要引入json文件也不是不可以,需要使用断言的方式引入
import data from './data.json' assert { type: "json" };
如果你不知道这个文件中抛出了什么方法或者属性,或者你想引入文件中的所有属性和方法,可以使用以下方式来引入
import * as all from './test.js'
console.log(all)
commonjs 和 ES module 的区别
- commonjs是基于运行时的同步加载而ES module是基于编译时的异步加载
什么意思?commonjs模块是在运行时同步加载的,这说明当node.js执行到require语句时,会同步地加载并执行相应的模块代码,如下例子,当运行到第三行时,同步加载并执行require
导入的代码块,并且此时,reqiure会阻塞后面的代码
const a = 1;
cpnsole.log(a);
const b = require('./test.js')
console.log(b)
ES module的加载是异步的,这意味着它不会阻塞主线程的执行。当遇到import
语句时,浏览器会并行地开始加载所需的模块,而不会等待模块完全加载完成再继续执行后续代码。import
只能在模块的顶层使用
这导致commonjs可以动态导入模块,而ES module 不可以
// 运行成功
if (true) {
const obj = require('./test.js')
}
// 报错
if (true) {
import obj from './test.js'
}
其实ESM还是有办法动态导入的,使用import()
if (true) {
import('./test.js').then(res=>{
console.log(res);
})
}
2. commonjs导入的值是可以可改的,ES module导入的值不可修改
先来看看commonjs
const obj = require('./test2.js')
console.log(obj);
obj.success = 2
obj.fn = function(a,b){
return a+b;
}
console.log(obj);
再看ES moudle
import obj,{name} from './test.js'
console.log(obj,name);
obj = {
a:123
}
// 修改obj的属性是允许的
// obj.success = 2
// obj.fn = function(a,b){
// return a+b;
// }
name = 'abc'
console.log(obj,name);
但是修改obj的属性是允许的
- commonjs中顶层的this指向这个模块本身,而ES6中顶层this指向undefined
结尾
commonjs和ES module的区别在面试中也经常被问到,希望到时候大家不会犯迷糊~
转载自:https://juejin.cn/post/7386494006224224283