【NodeJS】浅析 exports 与 module.exports 的区别 及 export default 与 export 的区别
2017-12-09 10:13
676 查看
模块的概念
模块分为两类:原生模块和文件模块。原生模块即 Node.js API 提供的原生模块,原生模块在启动时已经被加载。文件模块为动态加载模块,加载文件模块的工作主要由原生模块 module 来实现和完成。原生模块在启动时已经被加载,而文件模块则需要通过调用 Node.js 的 require 方法来实现加载。需要了解的一点是,Node.js 会对原生模块和文件模块都进行缓存,因此在第二次 require 该模块时,不会有重复开销去加载模块,只需要从缓存中读取相应模块数据即可。
exports 与 module.exports 的区别
exports 和 module.exports 的作用都是将文件模块的方法和属性暴露给 require 返回的对象进行调用。但是二者之间存在本质的区别。1)exports 的属性和方法都可以被 module.exports 替代
如下面的代码,其作用都是一致的。exports.name = 'bob' 和 module.exports.name = 'bob'
2)但 exports 不能替代 module.exports 方法
可以理解为包含关系。所有的 exports 对象最终都是通过 module.exports 传递执行,因此可以更确切地说,exports 是给 module.exports 添加属性和方法。为了验证这一点,我们将文件中的 module.exports 对象打印出来与 exports 方法和属性进行对比,代码如下:/* test.js */ exports.name = 'a'; exports.happy = function(console.log('happy')); console.log(module.exports); // 运行结果:{ name: 'a', happy: [Function] }
从结果中可以看出,module.exports 相当于 require 返回的
4000
对象,也就是所有 require 返回的对象,实质上结果和 module.exports 是相同的。这里我们可以做个检测,常见一个index.js文件,代码如下:
/* index.js */ var obj = require('./test.js'); console.log(obj); /* 运行结果: { name: 'a', happy: [Function] } { name: 'a', happy: [Function] } */
3)module.exports 方法还可以单独返回一个数据类型,而 exports 只能返回一个 object 对象。
当我们需要返回一个数组、字符串、数字等的类型时,就必须使用 module.exports。总结:
module.exports才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是module.exports而不是exports。所有的exports收集到的属性和方法,都赋值给了Module.exports。当然,这有个前提,就是module.exports本身不具备任何属性和方法。如果,module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。请看下例:/* test.js */ exports.a = function(){ console.log('a') } module.exports = {a: 2} exports.a = 1
/* index.js */ var obj = require('./test'); console.log(obj.a); /* 运行结果:2 */
说明:exports在module.exports 被改变后,失效。
export default 命令
使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。// export-default.js export default function () { console.log('foo'); }
上面代码是一个模块文件export-default.js,它的默认输出是一个函数。
其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
// import-default.js import customName from './export-default'; customName(); // 'foo'
上面代码的import命令,可以用任意名称指向export-default.js输出的方法,这时就不需要知道原模块输出的函数名。需要注意的是,这时import命令后面,不使用大括号。
export default命令用在非匿名函数前,也是可以的。
// export-default.js export default function foo() { console.log('foo'); } // 或者写成 function foo() { console.log('foo'); } export default foo;
export default 与 export 区别
export default 与 export 区别:1. export与export default均可用于导出常量、函数、文件、模块等
2. 你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用
3. 在一个文件或模块中,export、import可以有多个,export default仅有一个
4. 通过export方式导出,在导入时要加{ },export default则不需要
1.export //a.js export const str = "blablabla~"; export function log(sth) { return sth; } 对应的导入方式: //b.js import { str, log } from 'a'; //也可以分开写两次,导入的时候带花括号 --------------------------- 2.export default //a.js const str = "blablabla~"; export default str; 对应的导入方式: //b.js import str from 'a'; //导入的时候没有花括号
使用export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名
以下引自 阮一峰的《ECMAScript 6 入门》
Module 概述
历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的require、Python 的import,甚至就连 CSS 都有@import,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。CommonJS规范
这种模块加载机制被称为 CommonJS 规范。在这个规范下,每个 .js 文件都是一个模块,它们内部各自使用的变量名和函数名都互不冲突,例如,hello.js 和 main.js 都申明了全局变量 var s = ‘xxx’,但互不影响。
一个模块想要对外暴露变量(函数也是变量),可以用module.exports = variable; ,一个模块要引用其他模块暴露的变量,用var ref = require(‘module_name’); 就拿到了引用模块的变量。
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
// CommonJS模块 let { stat, exists, readFile } = require('fs'); // 等同于 let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile;
上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
// ES6模块 import { stat, exists, readFile } from 'fs';
上面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。
相关文章推荐
- module.exports与exports,export与export default之间的关系和区别
- exports与module.exports,export与export default 之间的关系和区别
- module.exports与exports,export与export default之间的关系和区别
- module.exports与exports,export与export default之间的关系和区别
- module.exports | exports | export | export default的区别
- module.exports与exports,export与export default之间的关系和区别
- module.exports与exports,export与export default之间的关系和区别
- nodejs中exports与module.exports的区别
- 【nodejs】exports 和 module.exports 的区别
- Node中Exports与module.export的使用与区别
- nodejs 中 module.exports 和 exports 的区别
- nodejs中exports与module.exports的区别
- nodejs中exports与module.exports的区别
- nodejs中exports与module.exports的区别
- nodejs中exports与module.exports的区别
- nodejs中exports与module.exports的区别详细介绍
- nodejs中module.exports和exports的区别辟谣!网上好多说法都有错误
- nodejs中exports与module.exports的区别详细介绍
- module.export和export区别 nodejs
- nodejs中export与module.exports