关于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 同时提交多个Web表单的方法
Feb 19 Javascript
一个收集图片的bookmarlet(js 刷新页面中的图片)
May 27 Javascript
jQuery源码分析-05异步队列 Deferred 使用介绍
Nov 14 Javascript
无闪烁更新网页内容JS实现
Dec 19 Javascript
JavaScript字符串对象(string)基本用法示例
Jan 18 Javascript
一道面试题引发的对javascript类型转换的思考
Mar 06 Javascript
微信小程序修改swiper默认指示器样式的实例代码
Jul 18 Javascript
详解webpack模块加载器兼打包工具
Sep 11 Javascript
小程序开发中如何使用async-await并封装公共异步请求的方法
Jan 20 Javascript
vue实现form表单与table表格的数据关联功能示例
Jan 29 Javascript
基于html+css+js实现简易计算器代码实例
Feb 28 Javascript
解决vscode进行vue格式化,会自动补分号和双引号的问题
Oct 26 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垃圾回收机制引用计数器概念分析
2013/06/24 PHP
php计算到指定日期还有多少天的方法
2015/04/14 PHP
php文件压缩之PHPZip类用法实例
2015/06/18 PHP
PHP基于ICU扩展intl快速实现汉字转拼音及按拼音首字母分组排序的方法
2017/05/03 PHP
php工具型代码之印章抠图
2018/07/18 PHP
解决laravel资源加载路径设置的问题
2019/10/14 PHP
Laravel 自动转换长整型雪花 ID 为字符串的实现
2020/10/27 PHP
javascript 数字格式化输出的实现代码
2013/12/10 Javascript
jquery的live使用注意事项
2014/02/18 Javascript
JS将数字转换成三位逗号分隔的样式(示例代码)
2014/02/19 Javascript
js判断url是否有效的两种方法
2014/03/04 Javascript
javascript操作Cookie(设置、读取、删除)方法详解
2015/03/18 Javascript
JQuery复制DOM节点的方法
2015/06/11 Javascript
在AngularJS中使用AJAX的方法
2015/06/17 Javascript
jQuery实现的简单折叠菜单(折叠面板)效果代码
2015/09/16 Javascript
AngularJs bootstrap搭载前台框架——准备工作
2016/09/01 Javascript
详解用node-images 打造简易图片服务器
2017/05/08 Javascript
记录一篇关于redux-saga的基本使用过程
2018/08/18 Javascript
JS实现十分钟倒计时代码实例
2018/10/18 Javascript
vue webpack build资源相对路径的问题及解决方法
2020/06/04 Javascript
jQuery实现增删改查
2020/12/22 jQuery
[52:02]完美世界DOTA2联赛PWL S2 FTD.C vs SZ 第一场 11.27
2020/11/30 DOTA
使用Python中的线程进行网络编程的入门教程
2015/04/15 Python
python实现马耳可夫链算法实例分析
2015/05/20 Python
Python工程师面试题 与Python Web相关
2016/01/14 Python
python3 判断列表是一个空列表的方法
2018/05/04 Python
浅谈python中np.array的shape( ,)与( ,1)的区别
2018/06/04 Python
Django之模型层多表操作的实现
2019/01/08 Python
pyqt5 实现工具栏文字图片同时显示
2019/06/13 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
2020/06/24 Python
使用html2canvas将页面转成图并使用用canvas2image下载
2019/04/04 HTML / CSS
2014年教师节演讲稿范文
2014/09/10 职场文书
2014年乡镇妇联工作总结
2014/12/02 职场文书
2016新年慰问信范文
2015/03/25 职场文书
表扬信范文
2015/05/04 职场文书
班主任工作经验交流会总结
2015/11/02 职场文书