关于JS模块化的知识点分享


Posted in Javascript onOctober 16, 2019

模块化是一个语言膨胀的必经之路,它能够帮助开发者拆分和组织代码。

Module模式

在模块化规范形成之前,JS开发者使用Module设计模式来解决JS全局作用域的污染问题。Module模式最初被定义为一种在传统软件工程中为类提供私有和公有封装的方法。在JavaScript中,Module模式使用匿名函数自调用 (闭包)来封装,通过自定义暴露行为来区分私有成员和公有成员。

let myModule = (function (window) {
  let moduleName = 'module' // private
  // public
  function setModuleName(name) {
   moduleName = name
  }
  // public
  function getModuleName() {
   return moduleName
  }
  return { setModuleName, getModuleName } // 暴露行为
 })(window)

上面例子是Module模式的一种写法,它通过闭包的特性打开了一个新的作用域,缓解了全局作用域命名冲突和安全性的问题。但是,开发者并不能够用它来组织和拆分代码,于是乎便出现了以此为基石的模块化规范。

模块化规化

1. CommonJS

CommonJS主要用在Node开发上,每个文件就是一个模块,没个文件都有自己的一个作用域。通过module.exports暴露public成员。例如:

// 文件名:x.js
let x = 1;
function add() {
 x += 1;
 return x;
}
module.exports.x = x;
module.exports.add = add;

此外,CommonJS通过require()引入模块依赖,require函数可以引入Node的内置模块、自定义模块和npm等第三方模块。

// 文件名:main.js
let xm = require('./x.js');
console.log(xm.x); // 1
console.log(xm.add()); // 2
console.log(xm.x);  // 1

从上面代码我们可以看出,require函数同步加载了x.js,并且返回了module.exports输出字面量的拷贝值。可能有人会问module.exports.x = x;不是赋值吗,怎么肥事呢?我们说,Module模式是模块化规范的基石,CommonJS也是对Module模式的一种封装。我们完全可以用Module模式来实现上面的代码效果:

let xModule = (function (){
 let x = 1;
 function add() {
  x += 1;
  return x;
 }
 return { x, add };
})();
let xm = xModule;
console.log(xm.x); // 1
console.log(xm.add()); // 2
console.log(xm.x);  // 1

通过Module模式模拟的CommonJS原理,我们就可以很好的解释CommonJS的特性了。因为CommonJS需要通过赋值的方式来获取匿名函数自调用的返回值,所以require函数在加载模块是同步的。然而CommonJS模块的加载机制局限了CommonJS在客户端上的使用,因为通过HTTP同步加载CommonJS模块是非常耗时的。

2. AMD和CMD

2.1 AMD

// 定义AMD规范的模块
define([function() {
 return 模块
})

区别于CommonJS,AMD规范的被依赖模块是异步加载的,而定义的模块是被当作回调函数来执行的,依赖于require.js模块管理工具库。当然,AMD规范不是采用匿名函数自调用的方式来封装,我们依然可以利用闭包的原理来实现模块的私有成员和公有成员:

define(['module1', 'module2'], function(m1, m2) {
 let x = 1;
 function add() {
  x += 1;
  return x;
 }
 return { add };
})

2.2 CMD

CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。AMD 推崇依赖前置,CMD 推崇依赖就近。

define(function(require, exports, module) {
 // 同步加载模块
 var a = require('./a');
 a.doSomething();
 // 异步加载一个模块,在加载完成时,执行回调
 require.async(['./b'], function(b) {
  b.doSomething();
 });
 // 对外暴露成员
 exports.doSomething = function() {};
});
// 使用模块
seajs.use('path');

CMD集成了CommonJS和AMD的的特点,支持同步和异步加载模块。CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的。因此,在CMD中require函数同步加载模块时没有HTTP请求过程。

ES6 module

ES6的模块化已经不是规范了,而是JS语言的特性。随着ES6的推出,AMD和CMD也随之成为了历史。ES6模块与模块化规范相比,有两大特点:

  • 模块化规范输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • 模块化规范是运行时加载,ES6 模块是编译时输出接口。

模块化规范输出的是一个对象,该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,ES6 module 是一个多对象输出,多对象加载的模型。从原理上来说,模块化规范是匿名函数自调用的封装,而ES6 module则是用匿名函数自调用去调用输出的成员。两者的区别可参考Babel and CommonJS modules。

以上就是本次介绍的全部知识点内容,感谢大家的学习和对三水点靠木的支持。

Javascript 相关文章推荐
JavaScript 自动分号插入(JavaScript synat:auto semicolon insertion)
Nov 04 Javascript
Java遍历集合方法分析(实现原理、算法性能、适用场合)
Apr 25 Javascript
基于Vuejs框架实现翻页组件
Jun 29 Javascript
jQuery选择器实例应用
Jan 05 Javascript
JavaScript拖动层Div代码
Mar 01 Javascript
js自定义瀑布流布局插件
May 16 Javascript
在Js页面通过POST传递参数跳转到新页面详解
Aug 25 Javascript
基于AngularJs select绑定数字类型的问题
Oct 08 Javascript
微信小程序外卖选购页实现切换分类与数量加减功能案例
Jan 15 Javascript
详解如何运行vue项目
Apr 15 Javascript
vue中img src 动态加载本地json的图片路径写法
Apr 25 Javascript
vue-路由精讲 二级路由和三级路由的作用
Aug 06 Javascript
vue-cli+iview项目打包上线之后图标不显示问题及解决方法
Oct 16 #Javascript
使用JavaScrip模拟实现仿京东搜索框功能
Oct 16 #Javascript
微信小程序如何实现在线客服功能
Oct 16 #Javascript
Vue 实现从文件中获取文本信息的方法详解
Oct 16 #Javascript
Vue 实现从小到大的横向滑动效果详解
Oct 16 #Javascript
JQuery实现ul中添加LI和删除指定的Li元素功能完整示例
Oct 16 #jQuery
JS使用正则表达式提交页面验证的代码
Oct 16 #Javascript
You might like
一些 PHP 管理系统程序中的后门
2009/08/05 PHP
php数组函数序列之end() - 移动数组内部指针到最后一个元素,并返回该元素的值
2011/10/31 PHP
PHPWind与Discuz截取字符函数substrs与cutstr性能比较
2011/12/05 PHP
PHP数组排序之sort、asort与ksort用法实例
2014/09/08 PHP
PHP二进制与字符串之间的相互转换教程
2016/10/14 PHP
JavaScript中令你抓狂的魔术变量
2006/11/30 Javascript
jQuery EasyUI API 中文文档 - Tabs标签页/选项卡
2011/10/01 Javascript
精心挑选的12款优秀的基于jQuery的手风琴效果插件和教程
2012/08/22 Javascript
JQuery获取与设置HTML元素的内容或文本的实现代码
2014/06/20 Javascript
实现无刷新联动例子汇总
2015/05/20 Javascript
js实现表单提交后不重新刷新当前页面
2016/11/30 Javascript
JS实现仿百度文库评分功能
2017/01/12 Javascript
JS实现的数组去除重复数据算法小结
2017/11/17 Javascript
React styled-components设置组件属性的方法
2018/08/07 Javascript
详解Vue用cmd创建项目
2019/02/12 Javascript
如何利用javascript接收json信息并进行处理
2020/08/06 Javascript
Python挑选文件夹里宽大于300图片的方法
2015/03/05 Python
在Python中使用swapCase()方法转换大小写的教程
2015/05/20 Python
使用python3+xlrd解析Excel的实例
2018/05/04 Python
Selenium定位元素操作示例
2018/08/10 Python
使用python接入微信聊天机器人
2020/03/31 Python
Python+selenium点击网页上指定坐标的实例
2019/07/05 Python
Python socket非阻塞模块应用示例
2019/09/12 Python
Python os库常用操作代码汇总
2020/11/03 Python
HTML5 层的叠加的实现
2020/07/07 HTML / CSS
俄罗斯化妆品和香水网上商店:Iledebeaute
2019/01/03 全球购物
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗
2013/05/01 面试题
出口公司经理求职简历中的自我评价
2013/10/13 职场文书
不听老师话的万能检讨书
2014/10/04 职场文书
项目转让协议书
2014/10/27 职场文书
2014年艾滋病防治工作总结
2014/12/10 职场文书
党员承诺书格式范文
2015/04/28 职场文书
2015年幼儿园师德师风建设工作总结
2015/10/23 职场文书
python numpy中setdiff1d的用法说明
2021/04/22 Python
【海涛教你打DOTA】死灵飞龙第一视角解说
2022/04/01 DOTA
nginx rewrite功能使用场景分析
2022/05/30 Servers