commonJs && es6
commonjs
每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
每个模块内部,module
变量代表当前模块。这个变量是一个对象,它的exports
属性(即module.exports
)是对外的接口。加载某个模块,其实是加载该模块的module.exports
属性。
require
方法用于加载模块
以上来自CommonJS规范-阮一峰
commonjs的详细:可以从node的使用中获悉
nodejs 模块化
导出:
提供一个exports
对象用于导出当前模块的方法或变量,并且它是唯一导出的出口
在nodejs中,每一个文件当作一个模块,在模块中,还有一个module
对象,exports
是它的一个属性
两种导出方式:
1. exports.binary_search = binary_search;
2. module.exports = binary_search;
第一种方式:
const util = require('./binary_search');
使用需要util.binary_search(arr, 15)
第二种方式:
直接:util(arr, 15)
why?
测试1:
exports.binary_search = binary_search;
console.log(exports);
console.log(module);
// output
{ binary_search: [Function: binary_search] }
Module {
id: '.',
exports: { binary_search: [Function: binary_search] },
parent: null,
filename: 'E:\\Beginning_JavaScript\\testEloquentJs\\DataStrctrue\\binary_search.js',
loaded: false,
children: [],
paths:
[ 'E:\\Beginning_JavaScript\\testEloquentJs\\DataStrctrue\\node_modules',
'E:\\Beginning_JavaScript\\testEloquentJs\\node_modules',
'E:\\Beginning_JavaScript\\node_modules',
'E:\\node_modules' ] }
// 对`exports`添加属性`binary_search`会影响到`module`对象(自动添加了)
测试2:
module.exports = binary_search;
console.log(exports);
console.log(module);
// output
{}
Module {
id: '.',
exports: [Function: binary_search],
// 对`module.exports`直接赋值不会影响到`exports`对象
// 而注意的是此时的require引用并不会因为`exports`对象为空,而是正常输出了
测试3:
module.exports.binary_search = binary_search;
console.log(exports);
console.log(module);
// output
{ binary_search: [Function: binary_search] }
Module {
id: '.',
exports: { binary_search: [Function: binary_search] },
...
// 对`module.exports`添加属性`binary_search`会影响到`exports`对象(自动添加了)
测试2:可知,require
是关联的module.exports
测试1和3:正好验证了exports
和module.exports
是指向同一个内存块(初始时),但是实际改变exports
的指向也不会改变module.exports
,exports
只是一个module.exports
引用,参看知乎回答的第一个回答
推荐知乎回答第二个回答的debug过程和最后的issue博客:
Node.js模块里exports与module.exports的区别?--知乎
exports、module.exports 和 export、export default 到底是咋回事
「前端」import、require、export、module.exports 混合详解
以及查看深入浅出Nodejs
的2.2.3 模块编译
的1. JavaScript模块的编译
最后其中module
对象的paths
的那个数组显得神奇(被叫做模块路径)...,参看2.2.2 路径分析和文件定位
es6
es6的语法就变得更加简洁:
//导出
//util1
export default {
a: 100
}
//util2
export const fn1 = function () {
console.log('fn1');
}
export const fn2 = function () {
console.log('fn2');
}
// 导入
import util from "./util1";
import { fn1, fn2 } from "./util2";
commonjs与es6互转的问题
主要是很奇怪的一种现象:一次在进行jest测试的时候,发现,
// utils.js
function fn1() {
console.log('fn1');
}
function fn2() {
console.log('fn2');
}
// 如上述,改成了commonjs的导出风格
module.exports = {
fn1,
fn2
}
// 导入(es6的导入风格)
import {fn1, fn2} from "./util2";
fn1();
fn2();
同样的这段代码,rollup
会报错,而webpack
可以正常跑
报错:
[!] Error: 'fn1' is not exported by src\util2.js
[[name] is not exported by [module]](https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module)
当改成:
export function fn1() {
console.log("fn1");
}
export function fn2() {
console.log("fn2");
}
rollup又可以正常运行。
这里很推荐阅读这篇文章:「前端」import、require、export、module.exports 混合详解
在文章里面就深度解析了,因为babel、webpack等会采用将es6的模块化转成commonJs的方式,所以在webpack里面的肯定是没有问题的,但rollup暂时我弄不懂哈哈哈