等MVC框架侵袭而来。CommonJS、AMD、NodeJS、RequireJS、SeaJS、curljs等模块化的JavaScript扑面而
来。web前端已经演变成大前端,web前端的发展速度之快。
1)我们来看看什么是模块化?
模块化是一种将系统分离成独立功能部分的方法,可将系统分割成独立的功能部分,严格定义模块接口、模块间具有透明性。javascript中的模块在一些C、PHP、java中比较常见:
c中使用include 包含.h文件php中使用require_once包含.php文件
java使用import导入包
此中都有模块化的思想。
2)模块化的优缺点:
a>优点:
可维护性
1.灵活架构,焦点分离
2.方便模块间组合、分解
3.方便单个模块功能调试、升级
4.多人协作互不干扰
可测试性
1.可分单元测试
b>缺点:
性能损耗
1.系统分层,调用链会很长
2.模块间通信,模块间发送消息会很耗性能
3)最近的项目中也有用到模块化,
使用的是seajs,但是当引用到jquery,jquery easyui/或者jquery
UI组件时,有可能会用到很多jquery插件,那这样要是实现一个很复杂的交互时,模块间的依赖会很多,使用define()方法引入模块会很多,不知
有么有什么好的方法?
4)附:
内聚度
内聚度指模块内部实现,它是信息隐藏和局部化概念的自然扩展,它标志着一个模块内部各成分彼此结合的紧密程度。好处也很明显,当把相关的任务分组后去阅读就容易多了。 设计时应该尽可能的提高模块内聚度,从而获得较高的模块独立性。
耦合度
耦合度则是指模块之间的关联程度的度量。耦合度取决于模块之间接口的复杂性,进入或调用模块的位置等。与内聚度相反,在设计时应尽量追求松散耦合的系统。
首先我们要明白一个前提,CommonJS模块规范和ES6模块规范完全是两种不同的概念。
我们知道在浏览器环境中,使用var声明一个全局变量会把该变量挂载到window对象上去,所以我们才可以访问到window.a
那如果是在node环境中呢?
如果我们在一个js文件中直接打印window是找不到这个顶层对象的,因为node环境下的顶层对象是global,
那我们声明的全局变量会不会像window对象一样挂载到global对象上呢?下面我们来试一下。
我们要想把变量a挂载到global对象上就必须要这样做
但是为什么会是undefined呢?
这就涉及到了模块化,在node环境中会存CommonJS模块化,它会把当前的文件当成模块的方式加载,那怎么理解以模块的方式加载呢?
我们可以简单的认为,每一个模块就是一个函数,模块中的内容就相当于是函数中的内容。
我们再想另一个问题,既然模块是一个函数,函数里的this指向是什么呢?
我们知道函数中的this是指向调用它的对象的,然而每个模块又是一个函数,node环境中的this又不能指向window,那会是指向谁呢?经过试验,发现node环境下的this指向的是一个空对象,这是因为node环境下的this指向的其实就是该模块导出的对象,默认是一个空对象
那我们如何让this指向全局对象global呢?很简单,把内容放到一个自执行函数里面就可以了,因为自执行函数里面的this永远指向全局对象
函数都会有arguments参数列表,而模块作为一个函数它的arguments又是什么呢?
module 和 exports 是Node.js给每个js文件内置的两个对象
在 a.js 中用 exports 或 module.exports 导出的对象,可以再另一个文件中通过该 require() 引用。
实际上,这两个对象指向同一块内存,也就是说他们两个是等价的(不去改变他们指向的内存地址)
require 引入的对象本质上是 module.exports .当 module.exports 和 exports 指向的不是同一块内存, exports 导出的内容就会失效。
我们在开发及接触新技术的时候,总会接触到该技术以何种规范编写,为了更加系统了解这些规范,本文总结了AMD,CMD,CommonJs,UMD,ESM几种规范,供大家学习了解。
AMD 是 RequireJS 在推⼴过程中对 模块定义的规范化 产出,它是⼀个概念,RequireJS是对这个概念的实现,就好⽐JavaScript语⾔是对ECMAScript规范的实现。AMD是⼀个组织,RequireJS是在这个组织下⾃定义的⼀套脚本语⾔
RequireJS:是⼀个AMD框架,可以异步加载JS⽂件,按照模块加载⽅法,通过define()函数定义。第⼀个参数是⼀个数组,⾥⾯定义⼀些需要依赖的包,第⼆个参数是⼀个回调函数,通过变量来引⽤模块⾥⾯的⽅法,最后通过return来输出()。
是⼀个 依赖前置 、 异步定义 的AMD框架(在参数⾥⾯引⼊js⽂件),在定义的同时如果需要⽤到别的模块,在最前⾯定义好即在参数数组⾥⾯进⾏引⼊,在回调⾥⾯加载
AMD 定义了一套 JavaScript 模块依赖异步加载标准,来解决同步加载的问题。模块通过 define 函数定义在闭包中,格式如下:
define(id?: String, dependencies?: String[], factory: Function|Object)
一些栗子:
注意:在 webpack 中,模块名只有局部作用域,在 Require.js 中模块名是全局作用域,可以在全局引用。
定义一个没有 id 值的匿名模块,通常作为应用的启动函数:
依赖多个模块的定义:
模块输出:
在模块定义内部引用依赖:
SeaJS 在推⼴过程中对模块定义的规范化产出,是⼀个同步模块定义,是SeaJS的⼀个标准,SeaJS是CMD概念的⼀个实现,SeaJS是淘宝团队提供的⼀个模块开发的js框架.
通过define()定义, 没有依赖前置 ,通过require加载模块,CMD是 依赖就近 ,在什么地⽅使⽤到模块就在什么地⽅require该模块,即⽤即返,这是⼀个 同步 的概念
在前端浏览器⾥⾯并不⽀持module.exports,CommonJS 是以在浏览器环境之外构建 JavaScript 生态系统为目标而产生的项目,比如在服务器和桌面环境中。
Nodejs端是使⽤CommonJS规范的,前端浏览器⼀般使⽤AMD、CMD、ES6等定义模块化开发的。输出⽅式有2种:默认输出module export 和带有名字的输出exports.area
CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。该规范的主要内容是,模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。
兼容AMD和commonJS规范的同时,还兼容全局引⽤的⽅式