一个小伙

require/exports | import/export

2019.01.31
  1. 规范不同;
  2. 时代不同;
  3. 形式不同; …

年末不算很忙,还是把拖了 N 月的 todo 整理了吧…总不能带到过年呀。O_O

前言

自我感觉,require/import 本身也是两个时代的产物,自我认知的区别性,规范不同,表达形式不同,出现时代不同,运行时期不同等。(以下 require 主要以 CommonJS 规范为例)

// require
const qs = require("qs");
// import
import Qs from "qs";

规范不同

require/exports 并非官方规范,而是来之 CommonJS,(社区产物,当然除了 CommonJS(node) 还有 AMD(requirejs)、CMD(seajs) 等规范,CommonJS 作为 Nodejs 的规范,一直沿用至今)。 import/export 则是来之官方,遵循 ECMAScript 规范,由 ES6 开始引入。

时代不同

在 ES6 之前,JavaScript 不支持类(class),所以也没有模块(module)。但是社区是伟大的,出现了如 CommonJS 等第三方社区规范,Nodejs 的出现也标志着“JS 模块化编程”的诞生。

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

形式不同

require

// a.js
module.exports = {
  value: "data",
  func: function() {}
};
// b.js
const a = require("./a");
a.value; // data
a.func();

import

// a.js
export default const func = function() {};
const value = "data";
export value;
// b.js
import A, { value } from "./a";

当然还有* as等,更多用法可见->import-MDN

本质差别

将 import/export 使用 babel 转成 es5 可以看到明显差别:

// es6
import Demo from "./demo";
// es5

"use strict";

var _demo = require("./demo");

var _demo2 = _interopRequireDefault(_demo);

function _interopRequireDefault(obj) {
  return obj && obj.__esModule ? obj : { default: obj };
}

当然以上差异产生的原因是因为要实现 import/export 的export default。如果只是引用一个模块方法好像形式上也没什么区别:

// es6
import { demo } from "./demo";
// es5
"use strict";

var _demo = require("./demo");

我能感觉到的区别是,import是编译时加载,require是运行时加载。所以import只能在头部,而require相对宽松,甚至可以所为表达式使用。

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

参考: require,import 区别? - 寸志的回答 - 知乎