Time: 20190920

模块是具有特定功能的组成单元,不同模块负责不同的工作,然后会以某种方式联系到一起,形成完整的程序逻辑。

CommonJS

CommonJS是2009年社区提出的,包含模块、文件、IO和控制台在内的一系列标准。

Node.js采用的是CommonJS标准的一部分,并在此基础上做了一些变化。

CommonJS标准,最初是为服务端设计,而有了Browserify后,可以将CommonJS模块打包为在浏览器下可以运行的单个文件。

导致的结果是:客户端的代码可以按照CommonJS标准来写。

Browserify是运行在Node.js环境下的模块打包工具。

此外,借助于包管理工具,前端开发开始流行用CommonJS标准了。

模块的定义

CommonJS中,每个文件是一个模块

通过script标签引入和封装成CommonJS模块的区别是什么?

前者:顶层作用域是全局作用域,变量声明和函数声明时会污染全局环境。
后者:形成属于模块自身的作用域,变量和函数仅自己可访问,外部不可见。

导出

导出是模块向外暴露自身的唯一方式。

CommonJS标准中,导出模块的语法是:

module.exports = {}

比如:

module.exports = {name: 'calculator', add: function(a, b) {return a + b;}
}

这个module关键字从哪里来呢?可以理解为,CommonJS模块内部会存一个module对象用于存储当前模块的信息

module.exports用于指定模块对外暴露的内容,上面的代码导出了两个属性。

CommonJS也支持一种简单的导出语法:

exports.name = 'calculater';
exports.add = function(a, b) {return a + b;
}

可用下面的代码来理解:

var module = {exports: {},
}var exports = module.exports;

因此,一个是赋值语法,一个是添加属性的方式,不可以直接对exports赋值,这会导致失效,即和module这个对象失去了关联。

混用情况辨析

exports.add = function(a, b) {return a + b;
}module.exports = {name: "calculator"
}

上面最后只会导出一个name属性出来,add函数丢失。

还有一个小点需要注意的是,导出语句语法不表示代码的结尾,后面写的逻辑也会照常执行。

但一般比较好的习惯是,将导出语法写到文件末尾,这样的约定,代码比较好读。

导入

CommonJS采用的导入语法是:require

// calculator.js
module.exports = {add: function(a, b) {return a + b;}
}// index.js
const cal = require('./calculator.js')
const sum = cal.add(2, 3)
console.log(sum) // 5

require模块的两种情况

  • 第一次加载,首先执行此模块,导出内容
  • 第二次加载,此模块的代码不会在执行,导出上次的结果

就是会用模块的module对象记录一个属性,module.loaded

require可以只执行,产生作用,而不用它返回的内容。

另外,require可以接收表达式,可动态指定模块的加载路径。

看到这里,我们应该可以想到import/export这种语法,是的,我们下面就进入ES6模块标准~

ES6模块标准

ES6是JavaScript发展的一个转折点。因为JS诞生之初就没有模块的概念。

ES6是JS官方委员会正式采纳的模块化标准。

// calculator.js
export default {name: 'calculator',add: function(a, b) {return a + b;}
}
// index.js
import calculator from './calculator.js' // .js可以省略
const sum = calculator.add(2,3)
console.log(sum) // 5

在ES6模块化标准中,也是将每个文件当作一个模块,每个模块有自己的作用域。

ES6默认采用的是严格模式,即默认有use strict的效果。

导出

ES6语法下,导出关键字是export,有两种形式:

  • 命名导出,可导出多个
  • 默认导出,只能导出一个

命名导出

export const name = "calculator";
export const add = function(a, b) { return a + b };

上面是分别导出,还可以用下面的写法,统一导出:

const name = 'calculator';
const add = function(a, b) { return a + b };
export { name, add };

两种写法效果相同。

另外,命名导出时可以用as重命名。

const name = 'calculator';
const add = function(a, b) { return a + b };
export { name, add as getSum };

默认导出

只能导出一个。

export default {name: "calculator",add: function(a, b) {return a + b;}
}

这种export default表示对外导出一个default变量,所以无需变量声明,直接导出了值。

// 导出字符串
export default 'This is String';// 导出类
export default class {...}// 导出匿名函数
export default function() {...}

导入

ES6语法下,用import来导入。

导入命名模块

// calculator.js
const name = 'calculator';
const add = function(a, b) { return a + b; };
export { name, add };// index.js
import { name, add } from './calculator.js';
add(2, 3);

导入命名模块有两个要求:

  • import后面要跟一对大括号将导入的变量名包裹起来
  • 导入的变量名和导出的变量名完全一致

命名导出时可用as关键字进行重命名,导入时也可以。

import { name, add as getSum } from './calculator.js'

整体导入import * from xxx

将整体导入的结果赋予一个对象,从而导入的变量是该对象的属性。

导入默认模块

// calculator.js
export default {name: "calculator",add: function(a, b) { return a + b }
}// index.js
import myCalculator from './calculator.js'
myCalculator.add(2, 3)

默认导出,在导入时,直接在import后面跟一个变量名,此变量名自由指定,用于指代默认导出的值。

从形式上来说,加大括号包围的导入导出是命名的,裸的,不加大括号的是默认导入导出。

在React项目中,常见:

import React, { Component } from 'react';

就是二者的混用,即React是默认导出,而Component是命名导出的变量。

CommonJS和ES6的比较

本质区别:动态与静态

CommonJS对模块依赖的解决方式是动态的,ES6对模块依赖的解决是静态的

动与静: 动表示,模块的依赖关系在代码发生阶段。静表示模块的依赖关系建立在代码编译阶段。

在CommonJS中,require('./calculator.js')会将该模块中module.exports导出的结果加载进来,模块的路径可以动态加载,且支持传入表达式,还可以用代码逻辑判断是否加载模块等,非常灵活,是在模块被执行前判断不了的依赖关系。

所以说,在CommonJS中,模块的导入、导出在代码的运行阶段发生。

ES6模块则是声明式的写法,导入路径不能是表达式,且必须在模块的顶层作用域。

即,ES6是静态的模块写法,编译时就知道了模块的依赖的关系。

ES6模块相对于CommonJS的几个优点

  • 死代码的检测与排除
  • 模块变量的类型检查
  • 编译器优化

关于ES6和CommonJS标准的比较,下文继续展开。

2019.10 Update:

第一届PAT算法直播课培训班招募帖,欢迎点击查看详情、

END.

模块打包之CommonJS与ES6模块比较初探相关推荐

  1. springboot公共模块打包_解决SpringBoot多模块发布时99%的问题?

    每天都会分享Java架构文章,喜欢的朋友关注我.ps:文末有彩蛋,惊喜等着你 如果使用的是 SpringBoot 多模块的项目,在发布的时候可能遇到各种各样的问题.本文归纳了以下 8 个原则和发布时经 ...

  2. ES6模块体系及DDN区块链设计开发规范

    ES6模块体系及DDN开发规范 概述 得益于 ES6 和 TS的模块体系,DDN区块链可以快速拆解和迭代.没有这些模块化的基础,我们后面所有的工作都会受阻,可插拔.可视化.可配置等功能就成了一句空话, ...

  3. 你真的搞懂ES6模块的导入导出规则了吗

    前言 模块作为ES6规范的核心部分之一,在实际项目开发中经常会看到它的身影,那么我们是否真正了解它的相关规则呢,今天就带大家一起了解一下模块的导入导出规则 导入 ES6模块的导入(即import)大致 ...

  4. SpringBoot-多模块打包与问题排解

    SpringBoot-多模块打包问题解决 1.spring boot 多模块打包方式(jar) 整理模块之间的依赖关系 在idea编译器右边的maven projectects中的项目结构中找的带有r ...

  5. es6 混合commjs_前端模块化——CommonJS、ES6规范

    什么叫模块化? 对于一个复杂的程序,将其按照一定的规范封装成几个文件块,每一块向外暴露一些接口,但是块的内部数据是私有的,块与块之间通过接口通信.这个过程称为模块化. 模块化的好处 CommonJS ...

  6. 详解CommonJS模块与ES6模块

    详解CommonJS模块与ES6模块 历史上,JS一直没有模块体系,在ES6之前,最主要的是CommonJS和AMD两种.前者用于服务器,后者用于浏览器,ES6在语言标准的层面上实现了模块功能,使用简 ...

  7. es6 混合commjs_详谈commonjs模块与es6模块的区别

    到目前为止,已经实习了3个月的时间了.最近在面试,在面试题里面有题目涉及到模块循环加载的知识.趁着这个机会,将commonjs模块与es6模块之间一些重要的的区别做个总结.语法上有什么区别就不具体说了 ...

  8. javascript --- ES6模块与CommonJS模块的差异

    CommonJS模块是运行时加载,ES6模块是编译时输出接口 是因为CommonJS加载的是一个对象(module.exports属性),该对象只有在脚本运行结束时才会生成.而ES6模块不是对象,它的 ...

  9. ES6模块与commonJS模块的差异

    参考: 前端模块化 ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案. 其模块功能主要由两个命令构成:export和import.export命 ...

最新文章

  1. H3C 交换机S5130S软件版本升级
  2. 【Linux 内核 内存管理】优化内存屏障 ① ( barrier 优化屏障 | 编译器优化 | CPU 执行优化 | 优化屏障源码 barrier 宏 )
  3. 事务回滚什么意思 try_分布式事务 TCC-Transaction 源码分析——事务恢复
  4. NLP word2vec paper
  5. No error message available, result code: E_FAIL(0x80004005)
  6. JavaScript中setAttribute用法
  7. 圆形界面 开启相机_「基础篇三」手机摄影拍照界面详解
  8. 【转载】ArrayList 中数据删除 fail fast
  9. Go中数字转换字符串的正确姿势
  10. 一题多解 —— $?(命令返回状态)的检验
  11. win10 休眠设置无效_睡眠模式在Windows 10系统上不起作用?
  12. foremost文件删除恢复
  13. 软件产品需求分析模板
  14. java程序员到J2EE架构师
  15. 离散数学——基础推理
  16. 突破人生的瓶颈(心灵之灯)
  17. 华为路由器交换机命令汇总-持续更新
  18. mysql57压缩包安装教程
  19. 刚子扯谈:神马网络营销
  20. 反复流产胎停,也许是被抗磷脂综合征坑了!

热门文章

  1. wordpress上传文件报错的解决方法(413 Request Entity Too Large、超过upload_max_filesize文件中定义的php.ini值)
  2. python程序员面试题精选100题_在Python程序员面试中被问的最多的10道题
  3. python清理日志脚本_Python日志:如果在程序运行时删除了日志文件,则创建新的日志文件(RotatingFileHandler)...
  4. linux自动切换tty,Linux 中不适用功能键切换TTY
  5. mysql 不同的记录_Mysql通过一个限制条件,查出多条不同的记录
  6. xp怎么删除计算机用户,WinXp系统如何删除用户账户?Xp系统删除用户账号的方法...
  7. idea创建包怎么让包分层_IDEA让包分层显示的实现方式
  8. mint 安装chrome_在Linux Mint上安装Chrome –简单的分步指南
  9. servlet3异步 例子_异步Servlet示例
  10. memcached教程_Memcached教程