ES6与CommonJS中的模块处理的区别


Posted in Javascript onJune 13, 2018

ES6和CommonJS都有自己的一套处理模块化代码的措施,即JS文件之间的相互引用。

为了方便两种方式的测试,使用nodejs的环境进行测试

CommonJS的模块处理

使用require来引入其他模块的代码,使用module.exports来引出

// exportDemo.js
count = 1;
module.exports.count = count;
module.exports.Hello = function() {
 var name;
 this.setName = function(newName) {
 name = newName;
 }
 this.sayHello = function() {
 console.log("hello Mr." + name);
 }
 this.getId = function() {
 return count++
 }
}
// requireDemo.js
var {Hello} = require("./exportDemo")
var hello = new Hello();

hello.setName("Blank");
hello.sayHello();

在终端执行 node requireDemo.js ,返回结果为'hello Mr.Blank'

导出的Hello函数是原函数的一次拷贝,修改Hello函数的属性值不会对其他require的地方造成影响

var { Hello, count } = require('./exportDemo')
var hello = new Hello();
// 让count自增
console.log(hello.getId());
console.log(hello.getId());
// 发现获取的count还是原值
console.log(count)

// 真正的count其实是已经改了的
var newHello = new Hello();
console.log(newHello.getId())

var { Hello: newHello, count: newCount } = require('./exportDemo')
console.log(newCount, 'newCount');
// 再次require,取得的newHello和之前require的Hello指向同一个拷贝
console.log(newHello === Hello)

ES6的模块处理

nodejs中运行ES6风格的代码

nodejs默认是不支持ES6的模块处理方案的。

但是在8.5.0之后,ES6代码的文件格式定为mjs后,可使用 node --experimental-modules xxx.mjs 运行。

// exportDemo.mjs
export let a = 1;
// importDemo.mjs
import {a} from './exportDemo.mjs'
console.log(a)

与CommonJS模块处理的区别

CommonJS 模块输出的是一个值的拷贝(已在上一章验证),ES6 模块输出的是值的引用。

// exportDemo.mjs
export let counter = 1;
export function incCounter() {
 counter ++;
}
// importDemo.mjs
import { counter, incCounter } from './exportDemo.mjs'

incCounter();
console.log(counter)		// 打印结果为2,而不是初始值的1

CommonJS模块是运行时加载,ES6模块是编译时输出接口

Nodejs此类的运行环境会在一个闭包中运行CommonJS模块代码

(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});

ES6 模块不会缓存运行结果,而是动态地去被加载的模块取值,并且变量总是绑定其所在的模块。

// exportDemo.mjs
export let a = 1;
export const b = 2;
export let obj = {};

// importDemo.mjs
import { a, b } from './exportDemo.mjs'
console.log(a, b)
a = 1 // 报错,TypeError: Assignment to constant variable,export出来的值是一个只读引用
obj.x = 1	// 可以改变属性值

在ES6模块中我们更多地要去考虑语法的问题 export default

有时候我们会在代码发现 export default obj 的用法,那么这个default是用来干嘛的?

default是ES6引入的与export配套使用的关键字,用来给匿名对象、匿名函数设置默认的名字用的

export出来的值必须要有一个命名,否则从语法层次便会报错

让我们看一下以下几个会报错的错误例子

export匿名对象

export { x: 1 }	// 报错,SyntaxError:Unexpected token,这是一个编译阶段的错误

// 正确写法
export default { x: 1 }

export匿名函数

export function() {}	// 报错,SyntaxError: Unexpected token (

// 正确写法
export default function() {}

循环引用(recycling loading)

在复杂的模块中,可能会出现模块间的 互相引用

commonJS的循环引用运行机制

// a.js
exports.loaded = false;
var b = require('./b.js')
console.log("b in a is " + JSON.stringify(b))
exports.loaded = true;
console.log("a complete")
// b.js
exports.loaded = false;
var a = require('./a.js')
console.log("a in b is " + JSON.stringify(a))
exports.loaded = true;
console.log("b complete")
// main.js
var a = require('./a.js')
var b = require('./b.js')

console.log("a in main is" + JSON.stringify(a))
console.log("b in main is" + JSON.stringify(b))

执行指令 nodejs main.js

时序图下的执行步骤分解图如下所示:

ES6与CommonJS中的模块处理的区别 

ES6的循环引用运行机制

一个会报错的例子

// a.mjs
import { bar } from './b.mjs'

console.log(bar);
export let foo = 'foo from a.mjs'
// b.mjs
import { foo } from './a.mjs'

console.log(foo)

export let bar = 'bar from b.mjs'
// main.mjs
import { foo } from './a.mjs'
import { bar } from './b.mjs'

node main.mjs

时序图下的执行步骤分解图如下所示:

ES6与CommonJS中的模块处理的区别

ES6的循环引用要特别注意变量是否已被声明,若未被声明的块级作用域变量被其他模块引用时,会报错。

改进方案:循环引用中尽量去export可以提前确定的值(例如函数),其实我们总是希望去 引用模块执行完全后最终确定的变量

// a.mjs
import { bar } from './b.mjs'

console.log(bar());
export function foo() {
 return 'foo from a.mjs'
}
// b.mjs
import { foo } from './a.mjs'
console.log(foo());
export function bar() {
 return 'bar from b.mjs'
}
// main.mjs
import { foo } from './a.mjs'
import { bar } from './b.mjs'

node main.mjs

返回结果:

foo from a.mjs
bar from b.mjs

时序图下的执行步骤分解图如下所示:

ES6与CommonJS中的模块处理的区别 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery.fileEveryWhere.js 一个跨浏览器的file显示插件
Oct 24 Javascript
jquery插件jquery.confirm弹出确认消息
Dec 22 Javascript
Jquery轮播效果实现过程解析
Mar 30 Javascript
jQuery animate和CSS3相结合实现缓动追逐效果附源码下载
Apr 18 Javascript
Vuex2.0+Vue2.0构建备忘录应用实践
Nov 30 Javascript
清除浏览器缓存的几种方法总结(必看)
Dec 09 Javascript
vue父组件中获取子组件中的数据(实例讲解)
Sep 27 Javascript
vue-自定义组件传值的实例讲解
Sep 18 Javascript
Vue2 添加数据可视化支持的方法步骤
Jan 02 Javascript
Angular PWA使用的Demo示例
Jan 31 Javascript
vue-cli3添加模式配置多环境变量的方法
Jun 05 Javascript
js实现简单的点名器随机色实例代码
Sep 20 Javascript
浅谈webpack 构建性能优化策略小结
Jun 13 #Javascript
详解webpack运行Babel教程
Jun 13 #Javascript
Babel 入门教程学习笔记
Jun 13 #Javascript
Vue中在新窗口打开页面及Vue-router的使用
Jun 13 #Javascript
微信小程序支付功能 php后台对接完整代码分享
Jun 12 #Javascript
js replace 全局替换的操作方法
Jun 12 #Javascript
微信小程序自定义prompt组件步骤详解
Jun 12 #Javascript
You might like
解决了Ajax、MySQL 和 Zend Framework 的乱码问题
2009/03/03 PHP
jQuery Ajax 全解析
2009/02/08 Javascript
javascript 禁止复制网页
2009/06/11 Javascript
javascript数组去掉重复
2011/05/12 Javascript
JavaScript中的this关键字介绍与使用实例
2013/06/21 Javascript
jquery对元素拖动排序示例
2014/01/16 Javascript
Jquery之Bind方法参数传递与接收的三种方法
2014/06/24 Javascript
jQuery实现异步获取json数据的2种方式
2014/08/29 Javascript
深入理解JavaScript系列(18):面向对象编程之ECMAScript实现
2015/03/05 Javascript
javascript实现unicode与ASCII相互转换的方法
2015/12/10 Javascript
AngularJs实现ng1.3+表单验证
2015/12/10 Javascript
jQuery操作dom实现弹出页面遮罩层(web端和移动端阻止遮罩层的滑动)
2016/08/25 Javascript
聊一聊JS中的prototype
2016/09/29 Javascript
微信小程序小组件 基于Canvas实现直播点赞气泡效果
2020/05/29 Javascript
ES6新特性之函数的扩展实例详解
2017/04/01 Javascript
Bootstrap Tooltip显示换行和左对齐的解决方案
2017/10/11 Javascript
JS实现textarea通过换行或者回车把多行数字分割成数组并且去掉数组中空的值
2018/10/29 Javascript
JS使用对象的defineProperty进行变量监控操作示例
2019/02/02 Javascript
js实现3D旋转效果
2020/08/18 Javascript
antd多选下拉框一行展示的实现方式
2020/10/31 Javascript
python定时器使用示例分享
2014/02/16 Python
Python fileinput模块使用介绍
2014/11/30 Python
pandas 使用均值填充缺失值列的小技巧分享
2019/07/04 Python
Django中ORM找出内容不为空的数据实例
2020/05/20 Python
Python爬虫爬取糗事百科段子实例分享
2020/07/31 Python
详解如何修改jupyter notebook的默认目录和默认浏览器
2021/01/24 Python
浅析与CSS3的loading动画加载相关的transition优化
2015/05/18 HTML / CSS
中学生团员自我评价分享
2013/12/07 职场文书
服务型党组织建设典型材料
2014/05/07 职场文书
单位工作证明书格式
2014/10/04 职场文书
三方合作意向书范本
2015/05/09 职场文书
工作收入证明模板
2015/06/12 职场文书
《自然之道》读后感3篇
2019/12/17 职场文书
教你使用VS Code的MySQL扩展管理数据库的方法
2022/01/22 MySQL
详解JavaScript的计时器和按钮效果设置
2022/02/18 Javascript
HTML基本元素标签介绍
2022/02/28 HTML / CSS