共同点:
都是为了实现js代码的模块化,只是两种不同的方式而已。
问:
那为什么会出现两种方案呢,又有什么不同呢?
清楚几种模块化的方案:
- 野生规范:
require/exports
(1)requirejs遵循AMD;
(2)seajs遵循CMD;
(3)node的module遵循CommonJs。 - 名门正派:
import/export
(1)TC39制定的新的ECMAScript版本,即在ES6(ES2015)中包含进来。
虽然写法上有所不同,但都是为了能够间接实现模块化,保持较为一致的代码风格。
官方标准定义的模块化方案
即:import、export。
可是,标准毕竟是标准,各大浏览器和node终端要实现标准还是有一段距离的。目前都2018年了,各大主浏览器都还没实现,还得依赖转换工具(例如babel)将代码转为ES5之后浏览器才能解析。
所以这也就解释了为什么我们的工程化代码中nodeJS遵循的commonjs规范和ES6的模块化方案并存的现象。
两者的区别
- import是ES6标准中的模块化解决方案,require是node中遵循CommonJS规范的模块化解决方案。
- 后者支持动态引入,也就是
require(${path}/xx.js)
,前者目前不支持,但是已有提案。 - 前者是关键词,后者不是。
- 前者是编译时加载,必须放在模块顶部,在性能上比后者好一些;后者是运行时加载,理论来说放在哪里都可以。
- 前者采用的是实时绑定方式,即导入和导出的值都指向同一个内存地址,所以导入的值会随着导出值变化;而后者在导出时是指拷贝,就算导出的值变化了,导入的值也不会变化,如果想要更新导入的值,就要重新导入。
- 前者会编译成
require/exports
来执行。
一、 import的用法
- import导入模块
import { a } from 'test.js';
import * as test from 'test.js';
import { a as key, b as value } from 'test.js';
- import导出模块
export {}
export default {}
export default XX
- (导出一个类)
(1)命名导出(每个模块包含任意数量)
// test.js
var a = 'aaa';
var b = 'bbb';
var c = 'ccc';
export {
a,
b,
c
};
// demo.js
import test from './test';
console.log('===test===:', test); // ===test===: undefined
import { a } from './test.js';
console.log('===test===:', a); // ===test===: aaa
import * as test from './test';
console.log('===test===:', test); // ===test===: {a: "aaa", b: "bbb", c: "ccc", __esModule: true}
// 导出的test为一个module{},所有内容,截图链接:https://img.haomeiwen.com/i3098902/114f164d0eb3ed4f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
import { a as key, b as value } from './test';
console.log('===test===:', key + '-----' + value); // ===test===: aaa-----bbb
(2)默认导出(每个模块包含一个)
// test.js
var a = 'aaa';
var b = 'bbb';
var c = 'ccc';
var d = 'ddd';
export default {
a,
b,
c,
dd: d // 需要自定义属性名的,只能使用`export default`来导出,export {}不可以,会报错。
};
// demo.js
import test from './test';
// 实际上这个default就是一个语法糖,只不过default是es6的一个关键字。
// 等同于
import { default as test } from './test';
console.log('===test===:', test); // ===test===: {a: "aaa", b: "bbb", c: "ccc", dd: "ddd"}
import { a } from './test.js';
console.log('===test===:', a); // ===test===: undefined
import * as test from './test';
console.log('===test===:', test); // ===test===: {default: {…}, __esModule: true}
// 导出的test为一个module{},所有内容,截图链接:https://img.haomeiwen.com/i3098902/5054c2ed429bb7ab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
import { a as key, b as value } from './test';
console.log('===test===:', key + '-----' + value); // ===test===: undefined-----undefined
(3)模块重定向
在当前模块中,导出指定导入模块的默认导出(等于是创建了一个“重定向”)。
// test.js
let test1 = {
a: 1
}
const test2 = (x, y) => {
return x + y
}
export {
test1
}
export default test2;
// 重点:体现了重定向 module.js
// 这两种是重定向的标准写法
// 将export {} 原封不动导出去
export * from './test'; // 适用于 导出方式为export {}
// 导出出去的没有default属性,相当于导出的直接是default的值。
export { default } from './test'; // 适用于 导出方式为 export default xx;
// 页面引用 demo.js
import test2, { test1 } from './module';
console.log('test1', test1); // {a: 1}
console.log('test2', test2) // ƒ test2(x, y) { return x + y; }
二、require
- require导入模块
const test = require('./test.js');
- require导出模块
module.exports = {}
exports.xx = xx
(1)require导入模块就没那么复杂了,导出时是什么样,导入时就还是什么样:
// test.js
var a = 'aaa';
var b = 'bbb';
var c = 'ccc';
module.exports = {
a,
b,
c
};
// demo.js
const test = require('./test');
console.log('===test===:', test); // ===test===: {a: "aaa", b: "bbb", c: "ccc"}
// 当然,也可以这样导入解析,不需要babel也可以正确运行
const { c } = require('./test');
console.log('===test===:', c); // ===test===: ccc
(2)直接导出 - 不常用的方式
// test.js
var a = 'aaa';
var b = 'bbb';
var c = 'ccc';
exports.c = c;
// demo.js
const test = require('./test');
console.log('===test===:', test); // ===test===: {c: "ccc"}
// 同上面,也可以以这样导入
const { c } = require('./test');
console.log('===test===:', c); // ===test===: ccc
ok,将两者终于进行比较并做了笔记,后面就容易查阅和理解了,所列出来的情况都有进行代码演示,完全真实。。后面有补充的话会进行更新喔。。。
网友评论