ES6模块导入导出(export&&export default等)总结

4,992 阅读3分钟

写在前面

学习Node也有一段时间了,好多东西属于那种会用却不知道其原理的状态,自己也决心打破它,所以会不定期的总结一下自己所学到的东西。下面就梳理一下不同模块的导入导出方法之间的区别。


首先先看看模块导入导出有哪些方式:

模块导入方式有:require、import、import xxx from yyy、import {xx} from yyy
模块导出方式有:exports、module.exports、export、export.default

再看看其使用规则和范围:

 模块导入方面
 require: node和ES6都支持的模块导入方式
 import和import xxx from yyy和import {xx} from yyy:只有ES6支持
 
 模块导出方面
 module.exports/exports: node本身支持的模块导出方式
 export/import: 只有ES6支持的模块导出方式

CommonJS规范(node中模块的导入导出) 由于之前js没有很统一比较混乱,代码按照各自的喜好写并没有一个模块的概念,而这个规范说白了就是对模块的定义:

CommonJS定义模块分为:模块标识(module)、模块定义(exports)、模块引用(require)

然后问题来了上面的exports和module.exports之间又什么关系呢? 其实是这样的每一个node.js执行文件,都会自动创建一个exports和module对象,同时module对象会创建一个叫exports的属性,初始化的值是 {},也就是如下:

exports = module.exports = {}
exports和module.exports都会指向一个{}内存区域

下面举个例子:

//foo.js
let a = 24;

console.log(module.exports); //打印结果为 {}
console.log(exports); //打印结果为 {}

exports.a = 2400; // exports改变module.exports里面的内容为{a: 2400}

console.log(module.exports); //打印结果为 {a: 2400}
console.log(exports); //打印结果为 {a: 2400}

exports = '指向其他内存区域不再指向a'; //改变exports指向的内存区域

//test.js
let a = require('./foo');
console.log(a); //打印结果为 {a: 2400}

由此结果可以很清晰的看出,require导入进来的内容是module.exports导出的所指向内存a的内容并不是exports的。说白了exports就是领导(module.exports)的秘书只负责起草稿子,出去念稿子的还是领导(module.exports)。

如果用内存概念去理解的话,应该就是exports和module.exports最开始都指向一个内存块(a),然后exports手贱修改了内存块(a)里面的内容但是exports和module.exports都还是指向a,然后exports又指向了其他内存,最后暴露出去的是module.exports所指向的内存块(a)的内容。最后为了避免分不清统一使用module.exports导出用require导入就OK了。


ES6中的模块导入导出 ES6出来之后模块的导入导出方法开始丰富起来,导出有export和export default,导入有import xxx from yyy 、import {xxx} from yyy

首先先看看导出export和export default之间的区别:

  • export与export default都可以导出常量、函数、文件、模块等。
  • 在文件或模块中,export default有且仅有一个,export可以有多个。
  • export可以直接导出变量表达式,export default不行。
  • 通过export方式导出时,导入需要加{},export default则不用。

下面也是老样子上代码举例:

//foo.js
'use strict'

//导出变量
export const a = 'ES6的export导出常量'
const b = 24;
export default b; //不能写 export defult const b = 24;

//导出function
export const func1 = function(){
    console.log('ES6的export导出function1')
}
export const func2 = function(){
    console.log('ES6的export导出function2')
}
export {func1,func2}


//test.js
'use strict'
const express = require('express');
const router = express.Router();

import {func1, func2} from './foo.js'; //导入export导出的两个function
import b from './foo.js'; //导入 export default导出的常量b
import * as testModule from './foo.js'; //as是作为集合成对象导入


/*GET HOME PAGE */
router.get('/',function(req,res,next){
    func1(); //ES6的export导出function1
    func2(); //ES6的export导出function2
    console.log(b); // 24
    testModule.func1(); //ES6的export导出function1
    testModule.func2(); //ES6的export导出function2
    console.log(testModule.b); //undefined,因为as导出是把零散的export合成一个对象而export default是导出为default属性
    console.log(testModule.default); // 24
}
module.exports = router;

最后

总算写完了,希望对大家有所启发或者帮助,今天周五了大家可以稍稍休息哈了。其中也有参考了一些文档和社区小伙伴写的一些总结。