模块化的开发方式可以提高代码的服用效率,方便进行代码的管理。模块化主要体现的是一种分而治之的思想。分而治之是复杂系统开发和维护的基石,模块化则是前段最流行的分治阶段。
模块化简介
具有相同属性和行为的事物的集合,在前端中,将一些属性比较类似和行为比较类似的内容放在同一个 JS 文件里面,把这个 JS 文件称为一个模块,为了每个 JS 文件只关注自身有关的事情,让每个 JS 文件各行其职
模块化要有几个特点:独立,完整,依赖关系
在最开始的阶段,JS 并没有模块化机制,各种 JS 到处飞,也就是所谓的野生代码,得不到妥善的管理。后来前端圈开始制定规范,最耳熟能详的是CommonJS
和AMD
。node.js
就是CommonJS
规范的产物。但是由于CommonJS
同步加载更适合服务端,所以迫切需要一个关于客户端的规范,既又出现了很多客户端,耳熟能详的AMD
模块化的实现
- 函数
- 对象的写法
- 匿名函数、返回对象
- 以来传入实参
- 以上缺点依赖关系不好处理,需要按顺序加载,可能会阻塞页面
模块化开发怎么做
立即执行函数,不暴露私有成员
1 | var module1 = (function() { |
模块化的好处
- 避免命名冲突
- 更好的分离,按需加载
- 更高复用性
- 高可维护性
同步加载 CommonJS
根据CommonJS
规范,每一个文件就是一个模块,其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。
该规范最初是用来服务器端的 node,前端的 Webpack 也是对 CommonJS 原生支持
CommonJS
的核心思想就是通过 require
方法来同步加载所要依赖的其他模块,然后通过 exports
或者 mode.exports
来导出需要暴露的接口
使用
1 | // index.js |
特点
- 所有代码都运行在模块作用域,不会污染全局作用域
- 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存
- 模块加载的顺序,按照其在代码中出现的顺序
require
命令的基本功能是,读取并执行一个 JavaScript 文件,然后返回该模块的 exports 对象。如果没有发现指定模块,会报错!
模块加载机制
CommonJS
模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块的内部变化就影响不到这个值
1 | // module.js |
上面的代码说明,当module.js
中的值被输出之后,模块内部的变化已经就影响不到这个值了。这是因为 counter 是一个原始类型值,会被缓存。除非写成一个函数,才能得到内部变动的值
注意: 浏览器不兼容 CommonJS
,原因是浏览器缺少 module
、exports
、require
、global
四个环境变量。如要使用需要工具转换。
CommonJS 采用同步加载不同模块文件,适用于服务端
因为模块文件都存放在服务器的各个硬盘上,读取加载时间快,适合服务端,不适应浏览器
异步加载 AMD
CommonJS 为服务器端而生,采用的同步加载方式。因此不适用与浏览器。因为浏览器需要到服务器加载文件,请求时间远大于本机读取时间,倘若文件较多,网络迟缓就会导致页面瘫痪,所以浏览器更希望能够实现异步加载的方式。
AMD 规范是实现异步加载模块,允许指定回调函数,等模块异步加载完成后即可调用回调函数。
AMD 的核心思想就是通过 define
来定义一个模块,然后使用 require
来加载一个模块
使用
1 | // main.js |
AMD 模块定义的方法非常清晰,不污染全局环境,能够清除的显示依赖关系。AMD 模式可以用于浏览器环境,并且允许非同步加载模块,也可以根据需要动态加载模块。
异步加载 CMD
CMD 异步加载,跟 AMD 的主要区别在于,AMD 依赖前置,提前加载依赖。而 CMD 就近加载,按需加载。
CMD 的核心思想就是通过 define 来定义一个模块,然后使用 require 来加载一个模块。
使用
1 | // module1.js |
ES6 模块化
ES6 自带模块化,可以使用 import
关键字引入模块,通过 export 关键字导出模块,功能较之前的几个方案更为强大,也是我们所推崇的,但是 ES6 目前无法在浏览器中执行,所以,我们只能通过 babel 将不被支持的 import 编译为当前受到广泛支持的 require
使用
1 | // index.js |
ES6 模块与 CommonJS 模块的差异
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
- ES6 模块是动态引用的,并且不会缓存值,模块里边的变量绑定其所在的模块
总结
- CommonJS 规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境中使用,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了 AMD 和 CMD 解决方案
- AMD 规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过 AMD 规范开发成本高,代码的阅读和书写比较困难,模块定义的方式语义不顺畅
- CMD 规范与 AMD 规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在 Node.js 中运行。不过,依赖 SPM 打包,模块的加载逻辑偏重
- ES6 在语言标准层面上,实现模块功能,而且实现的相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案
‘摘抄’不是单纯的“粘贴->复制”,而是眼到,手到,心到的一字一句敲打下来。
博客声明:所有转载的文章、图片仅用于作者本人收藏学习目的,被要求或认为适当时,将标注署名与来源。若不愿某一作品被转用,请及时通知本站,本站将予以及时删除。