作者:寸志
链接:https://www.zhihu.com/question/56820346/answer/150724784
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

遵循的模块化规范不一样

模块化规范:即为 JavaScript 提供一种模块编写、模块依赖和模块运行的方案。谁让最初的 JavaScript 是那么的裸奔呢——全局变量就是它的模块化规范。

require/exports 出生在野生规范当中,什么叫做野生规范?即这些规范是 JavaScript 社区中的开发者自己草拟的规则,得到了大家的承认或者广泛的应用。比如 CommonJS、AMD、CMD 等等。import/export 则是名门正派。TC39 制定的新的 ECMAScript 版本,即 ES6(ES2015)中包含进来。

出现的时间不同

require/exports 相关的规范由于野生性质,在 2010 年前后出生。AMD、CMD 相对命比较短,到 2014 年基本上就摇摇欲坠了。一开始大家还比较喜欢在浏览器上采用这种异步小模块的加载方式,但并不是银弹。随着 Node.js 流行和 Browsersify 的兴起,运行时异步加载逐渐被构建时模块合并分块所替代。Wrapper 函数再也不需要了。 2014 年 Webpack 还是新玩意,现在已经是前端必备神器了。

Browsersify、Webpack 一开始的目的就是打包 CommonJS 模块。

CommonJS 作为 Node.js 的规范,一直沿用至今。由于 npm 上 CommonJS 的类库众多,以及 CommonJS 和 ES6 之间的差异,Node.js 无法直接兼容 ES6。所以现阶段 require/exports 任然是必要且实必须的。出自 ES6 的 import/export 相对就晚了许多。被大家所熟知和使用也是 2015 年之后的事了。 这其实要感谢 babel(原来项目名叫做 6to5,后更名为 babel) 这个神一般的项目。由于有了 babel 将还未被宿主环境(各浏览器、Node.js)直接支持的 ES6 Module 编译为 ES5 的 CommonJS —— 也就是 require/exports 这种写法 —— Webpack 插上 babel-loader 这个翅膀才开始高飞,大家也才可以称 " 我在使用 ES6! "

这也就是为什么前面说 require/exports 是必要且必须的。因为事实是,目前你编写的 import/export 最终都是编译为 require/exports 来执行的。

require/exports 和 import/export 形式不一样

require/exports 的用法只有以下三种简单的写法:

const fs = require('fs')
exports.fs = fs
module.exports = fs

而 import/export 的写法就多种多样:

import fs from 'fs'
import {default as fs} from 'fs'
import * as fs from 'fs'
import {readFile} from 'fs'
import {readFile as read} from 'fs'
import fs, {readFile} from 'fs' export default fs
export const fs
export function readFile
export {readFile, read}
export * from 'fs'

require/exports 和 import/export 本质上的差别

形式上看起来五花八门,但本质上:

  1. CommonJS 还是 ES6 Module 输出都可以看成是一个具备多个属性或者方法的对象;
  2. default 是 ES6 Module 所独有的关键字,export default fs 输出默认的接口对象,import fs from 'fs' 可直接导入这个对象;
  3. ES6 Module 中导入模块的属性或者方法是强绑定的,包括基础类型;而 CommonJS 则是普通的值传递或者引用传递。

1、2 相对比较好理解,3 需要看个例子:

// counter.js
exports.count = 0
setTimeout(function () {
console.log('increase count to', ++exports.count, 'in counter.js after 500ms')
}, 500) // commonjs.js
const {count} = require('./counter')
setTimeout(function () {
console.log('read count after 1000ms in commonjs is', count)
}, 1000) //es6.js
import {count} from './counter'
setTimeout(function () {
console.log('read count after 1000ms in es6 is', count)
}, 1000)

分别运行 commonjs.js 和 es6.js:

➜  test node commonjs.js
increase count to 1 in counter.js after 500ms
read count after 1000ms in commonjs is 0
➜ test babel-node es6.js
increase count to 1 in counter.js after 500ms
read count after 1000ms in es6 is 1

JS require and import的更多相关文章

  1. JS 中的require 和 import 区别整理

    ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引入模块,使 ...

  2. 转:彻底搞清楚javascript中的require、import和export

    原文地址:彻底搞清楚javascript中的require.import和export   为什么有模块概念 理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. 但是,Ja ...

  3. 008_Node中的require和import

    一.js的对象的解构赋值 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuri ...

  4. NodeJS中的require和import

    ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引入模块,使 ...

  5. vue 更新了vue-cli到最新版本后引发的问题: require和import、vue-loader的问题

    "vue-loader": "^12.1.0", "vue-loader": "^12.1.0", "vue- ...

  6. javascript中的require、import和export模块文件

    CommonJS 方式 文件输出如math.js: math.add = function(a,b){ return a+b; }exports.math = math; 文件引入: math = r ...

  7. Node中没搞明白require和import,你会被坑的很惨

    ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引入模块,使 ...

  8. require和import的使用

    一.前言 ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引 ...

  9. require与import

    require 和 import,都是为了JS模块化使用.最近项目中,因为多人协同开发,出现了一个项目中同时使用了require 和 import 引入依赖的情况.正常情况下,一个项目中最好是对引入方 ...

随机推荐

  1. Oracle的rollup、cube、grouping sets函数

    转载自:https://blog.csdn.net/huang_xw/article/details/6402396 Oracle的group by除了基本用法以外,还有3种扩展用法,分别是rollu ...

  2. Https证书配置

    本文介绍配置免费证书的方法 具体步骤: 一.获取免费CA证书 步骤1到腾讯云找到: 二.申请完成 后域名验证指引 申请域名型证书,可以通过以下方式验证域名的所有权: 1. 手动 DNS 验证 通过解析 ...

  3. 爬虫之requests

    一.基本用法 1.GET请求 ①r=requests.get(url) --返回Response对象 def get(url, params=None, **kwargs): params={... ...

  4. python远程执行dos命令

    https://blog.csdn.net/huaihuaidexiao/article/details/5543240 https://blog.csdn.net/bcbobo21cn/articl ...

  5. 很不幸,装win10和Ubuntu双系统还是入坑了

    具体问题描述:在安装Ubuntu的时候,没有发现有与windows共存的提示,直接说本计算机没有安装系统.在安装完成后,发现通过BIOS只有进入Ubuntu的启动项,没有进入Windows的启动项. ...

  6. ASP.NET 实现PDF文件下载[转]

    本文介绍了一种在ASP.NET中下载文件的方法.方法一:可能是最简单的.最短的方式: 1 Response.ContentType = "application/pdf"; 2 R ...

  7. nodejs 实现文件拷贝

    通过4中不通的方式实现对一个文件的拷贝 方式一:readFile 异步一次性读取文件再写入 //异步形式读取文件 function copyFile(url){ const extName = pat ...

  8. SpringBoot 配置Redis

    application.properties 文件内容 #Redis数据库索引(默认为0) spring.redis.database=0 #Redis服务器地址 spring.redis.host= ...

  9. Nginx配置反向代理服务器

    首先,在阅读<深入理解Nginx模块>后,大体了解了配置反向代理服务器一些常见的配置.如下进行说明:” l  Nginx worker进程个数 语法: worker_processes n ...

  10. 结对项目-WordCount

    结对作业: 成员:201631062115(me),201631062613(partner) 代码地址:https://gitee.com/ackary/WordCount 作业的链接地址:http ...