一、CommonJS的导入导出

1、使用exports导出(注意是有s)
(1)注意:exports刚开始是一个空对象,我们可以在这个对象中添加很多个属性,添加的属性会被导出;

//这是 main.js文件
let name = 'miracle';
let age = 18;

function abc() {
  console.log('你好'+name);
}

exports.name = name;
exports.age = age;
exports.abc = abc;

(2)另外一个文件中可以导入:

//这是bar.js文件
const bar = require('./main.js');

(3)上面导入那行完成了什么操作呢?

1)意味着bar.js文件中的bar变量等于exports对象;
2)也就是require通过各种查找方式,最终找到了exports这个对象;
3)并且将这个exports对象赋值给了bar变量;
4) bar变量就是exports对象了

(4)注意:bar.js文件中的bar变量是exports对象引用赋值,所以在bar.js文件中修改bar变量的属性值,则exports中对应的属性值也会跟着变化,例如:

//这是main.js文件
let name = 'miracle';
let age = 18;
exports.name = name;
exports.age = age;
//这是bar.js文件
const bar = require('./main.js'); 
console.log(bar);//第一次输出bar

bar.name = 'abc';
console.log(bar);//第二次输出bar
//控制台输出的结果
{ name: 'miracle', age: 18 }
{ name: 'abc', age: 18 }

2、使用module.exports导出
(1)可以知道,Node中导出东西时,基本上是通过module.exports导出的,具体原因如下:

通过维基百科中对CommonJS规范的解析可知:
1)CommonJS中是没有module.exports的概念的;
2)但是为了实现模块(每一个js文件,就是一个模块)的导出,Node中使用的是Module的类,每一个模块都是Module的一个实例,也就是module
3)所以在Node中真正用于导出的其实根本不是exports,而是module.exports;
4)因为module才是导出的真正实现者;
5)但是,为什么exports也可以导出呢?
6)这是因为module对象的exports属性是exports对象的一个引用而已,即module对象的exports属性的引用指针指向exports对象;
7) 也就是说 module.exports = exports = bar.js中的bar对象;
8)所以严谨来说,本质上,Node中导出东西时,其实都是通过module.exports导出的;
9)注意(例外情况):当在一个js文件时,exports和module.exports同时存在,且导出不同对象时,要以module.exports导出的对象为准,因为本质上,Node中要导出东西时,都是通过module.exports导出的(一般情况下,module对象的exports属性的引用指针指向exports对象,但当module.exports的引用指针不指向exports时,导出的东西,要以module.exports为准);

二、ES6 模块导入导出

1、export的使用(注意,没有s)

//aaa.js文件
var name = '小明'
var age = 18
var flag = true

function sum(num1, num2) {
  return num1 + num2
}

if (flag) {
  console.log(sum(20, 30));
}

// 1.导出方式一:
export {
  flag, sum
}

// 2.导出方式二:
export var num1 = 1000;
export var height = 1.88


// 3.导出函数/类
export function mul(num1, num2) {
  return num1 * num2
}

export class Person {
  run() {
    console.log('在奔跑');
  }
}

//4.export default(只有一种方式)
//下面进行对比:

//export的两种方式
//const address = '北京市'
//export {
//  address
//}
//export const address = '北京市'

//export default的一种方式
const address = '北京市'
export default address

2、import的使用

// 1.导入的{}中定义的变量
import {flag, sum} from "./aaa.js";

if (flag) {
  console.log('小明是天才, 哈哈哈');
  console.log(sum(20, 30));
}

// 2.直接导入export定义的变量
import {num1, height} from "./aaa.js";

console.log(num1);
console.log(height);

// 3.导入 export的function/class
import {mul, Person} from "./aaa.js";

console.log(mul(30, 50));

const p = new Person();
p.run()

// 4.导入 export default中的内容
//addr的名字是随便取的
import addr from "./aaa.js";

// 5.统一全部导入
// import {flag, num, num1, height, Person, mul, sum} from "./aaa.js";

import * as aaa from './aaa.js'

console.log(aaa.flag);
console.log(aaa.height);

3、某些情况下,一个模块包含某个功能,我们并不希望给这个功能命名,而是让导入着自己命名,这个时候就可以使用export.default:

//info.js
const address = '北京市'
export default address
导入 export default中的内容
//addr的名字是自己随便取的
import addr from "./aaa.js";

4、另外,注意:export default在同一个模块中,不允许出现多个。