require/exports与import/export的差异

  • 历史背景

  • require/exports
    • 来自野生规范当中,即这些规范是JavaScript社区中的开发者自己草拟的规则,得到了大家的承认和广泛的应用,比如CommonJSAMDCMD等等。而Node遵循CommonJS规范,requireJS遵循 AMDAsynchronous Module Definition,即异步模块加载机制seaJS遵循CMD
    • 因为Node无法直接兼容ES6语法,所以现阶段require/exports仍然是必要且是必须的。
  • import/export
    • 来自ES6的新规范,即TC39 制定的新的 ECMAScript 版本。
    • babel诞生后,它能将还未被宿主环境(各大浏览器、Node)直接支持的ES6语法编译为ES5,也就是能将ES6 Moduleimport/export编译为CommonJSrequire/exports这种写法。

差异

写法差异

require/exports

/* 导出 */
exports.fs = fs;      // 单个特性导出,可导出多个
module.exports = fs;   // 整个模块导出,每个模块只包含一个

/* 引入 */
const fs = require('fs');   // 引入整个模块
复制代码

import/export

/* 导出 */
export default fs;     // 默认导出 每个模块包含一个 每次导出都会覆盖前一个导出
export const fs;       // 导出单个特性 每个模块包括多个
export function readFile;    // 导出单个特性 每个模块包括多个
export { readFile, read };   // 导出列表
export * from 'fs';     // 导出模块合集

/* 引入 */
import fs from 'fs';       // 引入整个模块的内容
import '/fs.js';          // 仅为副作用而引入一个模块 不导入模块中的任何接口
import * as fs from 'fs';    // 引入整个模块的内容
import { readFile } from 'fs';   // 引入readFile单个接口
import { readFile as read } from 'fs';   // 引入模块中read接口,并重命名为readFile
import fs , { readFile } from 'fs';   // 引入整个模块的内容和readFile接口
复制代码

输出差异

require/exports

require/exports 输出的是一个值的拷贝,也就是说,当你引入一个值,模块内部的变化是影响不到这个值的。

// test.js
let num = 0;
function addNum(){
  num++;
};
module.exports = {
  num: num,
  addNum: addNum
}

// main.js
const test = require('./test.js');

console.log(test.num);     // output: 0
test.addNum();
console.log(test.num);     // output: 0
复制代码

import/export

import/export输出的是值的索引,也就是说,该引用其实是一个动态引用,并不会缓存值,当模块内部发生变化,你的引入值也会随之更新。

// test.js
export let num = 0;
export function addNum(){
  num++;
};

// main.js
import { num, addNum } from './test.js';

console.log(num);     // output: 0
addNum();
console.log(num);     // output: 1
复制代码

加载差异

require/exports

CommonJS模块是运行时加载。

因为CommonJS模块加载的是一个对象,即module.exports属性,该对象只有在脚本运行完才生成,也因此没办法再编译时做“静态优化”。

const { test1, test2, test3 } = require('test');

/* 等同于 */
const _test = require('test');   // 实质上加载了整个模块,再从中读取这三个方法
const test1 = _test.test1;
const test2 = _test.test2;
const test3 = _test.test3;
复制代码

import/export

ES6模块是编译时输出接口。

ES6模块不是对象,它对外接口只是一个静态定义,在代码静态解析阶段才会生成,因此效率要比CommonJS模块加载高。

import { test1, test2, test3 } from 'test';   // 只从模块中加载这三个方法,其他的不加载
复制代码

异步差异

require/exports

CommonJS模块中的require是同步加载模块。

import/export

ES6模块的import命令是异步加载的,有一个独立的模块依赖的解析阶段。


作者:Dewey
链接:https://juejin.cn/post/6914939774276993038
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值