# JavaScript 模块化开发
方式简单化实现
+ 模块与模块之间相互协作构成了模块系统
- 程序模块化开发的优点
+ 开发效率高
* 代码方便重用,别人开发的模块直接拿过来就可以使用,不需要重复开发类似的功能
+ 可维护性高
* 软件的声明周期中最长的阶段其实并不是开发阶段,而是维护阶段,<br>需求变更比较频繁,使用模块化的开发方式更容易维护
历史上,JavaScript一直没有模块体系,
无法将一个大程序拆分成相互依赖的小文件,再用简单的方法拼接起来
其他语言,包括CSS都有这项功能,
但是JavaScript任何这方便的支持都是没有的,这对开发大型的、复杂的项目形成了障碍
## 02-Nodejs铺垫-模块化演变历程-全局函数
- 全局函数
+ 全局函数形成的模块只能人为的认为他们属于一个模块
+ 但是程序并不能区分哪些函数是同一个模块
- 全局函数容易造成的问题
+ 污染了全局变量,无法保证不与其他模块发生变量名冲突
+ 从代码阅读上来说:模块成员之间看不出之间的关系
## 03-Nodejs铺垫-模块化演变历程-对象封装 (命名空间法)
所谓的命名空间,就是对象上加了一个属性或者方法
- 对象封装-命名空间
+ 通过添加命名空间的形式从某种程度上解决了变量命名冲突的问题,但是并不能从根本上解决命名冲突
+ 从代码级别可以明显的区别出哪些函数属于同一模块
- 对象封装-命名空间造成的问题
+ 暴露了所有的模块成员,内部状态可以被外部改写,不安全
+ 命名空间越来越长
## 04-Nodejs铺垫-模块化演变历程-隔离公有私有成员 (私有空间)(重要)
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
如果不通过return,外部是无法访问到内部的属性和方法的,无法修改
形成了一个隔离作用域,
可以把模块自己使用的成员封装到模块内部,降低了对全局作用域的污染
其实就是降低命名冲突的概率,隔离公有私有成员
通过匿名自执行函数,利用函数作用域的机制隔开私有变量
- 私有共有成员分离
+ 私有空间的变量和函数不会影响全局作用域
+ 公开公有方法,隐藏私有空间
var on = (function(){
1、私有的函数
2、公有的部分
return
})()
## 05-Nodejs铺垫-模块化演变历程-增强模块可维护性(了解,多写熟悉)
- 模块的维护和拓展
+ 可以采用直接赋值的形式扩展这个模块,防止了模块的名称被冲突
+ 在加载模块的时候,不需要在考虑顺序的问题,但是采用着这种方式,一定要遵守这种规范
开闭原则
var on = (function(){
1、私有的函数
2、公有的部分
return
})()
var on = (function(o){
1、私有的函数
2、公有的部分
return
})(one || {})
## 06-Nodejs铺垫-模块化演变历程-添加第三方依赖
一定要把依赖项通过参数的形式注入进来,然后在内部使用注入的属性<br>
不要直接在模块内部使用第三方依赖
- 模块的第三方依赖
+ 模块最好要保证模块的职责单一性,最好不要与程序的其他部分直接交互
+ 通过向匿名函数注入依赖项的形式,除了保证模块的独立性,还使模块之间的依赖关系变的更加明显
- 好处
+ 提高了代码的执行性能,减少了变量作用域的查找层数
+ 增加了代码的可读性,能直观的看当前文件模块依赖的其他模块
var on = (function(o, abc){
1、私有的函数
2、公有的部分
return
})(one || {}, jQuery)
## 上面几种模块化演变历程方法的总结
- 规范
+ 最大的问题,还是规范的问题
+ 如果在多人协作开发过程中,会有很大的问题
+ 多人协作开发阶段:代码的风格一定要统一
## 07-Nodejs铺垫-初识模块化框架Seajs
- 简单介绍一下这些标准
+ CMD
* seaJS
* 玉伯
+ AMD
* requireJS
+ commonJS
## 08-Nodejs铺垫-Seajs基本使用
- 使用seajs的步骤
+ 1、引入seajs
+ 2、如何定义模块
* define // 参数的名字不允许修改,参数可以是多个
* define(function(require, exports, module){});
+ 3、如何公开模块成员
* exports
* seajs.use两个参数
- 模块的路径
- 回调函数 -- 回调函数的参数指成的是exports
+ 4、如何依赖模块
* require()
## 09-Nodejs铺垫-Seajs模块定义参数分析
- exports 与 module.exports
+ 它们两个实际上是一个对象
+ exports 对外提供接口
+ module.exports 对外提供了整个接口
- require
+ 加载外部的模块
+ require 是一个方法,接受模块标识作为唯一参数,用来获取其他模块提供的接口。
- exports
+ exports 是一个对象,用来向外提供模块接口。
- module
+ module 是一个对象,上面存储了与当前模块相关联的一些属性和方法。
- module有几种属性和方法
+ module.id (模块id,就是全路径了,一般情况下(没有在 define 中手写 id 参数时),module.id 的值就是 module.uri,两者完全相同。)
+ module.exports(对外接口,{}格式,exports 仅仅是 module.exports 的一个引用。)
+ module.dependencies(数组,当前模块依赖的模块)
## 10-Nodejs铺垫-Seajs模块导出成员原理分析(重要)
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
exports 与 module.exports 的区别
其实,Module.exports才是真正的接口,exports只不过是它的一个辅助工具。
最终返回给调用的是Module.exports而不是exports。
所有的exports收集到的属性和方法,都赋值给了Module.exports。
当然,这有个前提,就是Module.exports本身不具备任何属性和方法。
如果,Module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略
- 如果导出的是单个成员,那么一般使用exports.成员名称 这种形式导出
- 如果导出的是一个对象,那么一般使用module.exports这种形式导出
## 11-Nodejs铺垫-Seajs异步加载模块
Seajs异步加载模块的写法
> require.async("模块地址",function(){})
require.async('./')
## 12-Nodejs铺垫-Seajs依赖jQuery
- 如何设置jQuery依赖
```js
if ( typeof noGlobal === strundefined ) {
window.jQuery = window.$ = jQuery;
if ( typeof define === "function" ) {
define(function(){return jQuery});
}
}
```
- seaJS如何配置参数
```js
seajs.config({
alias : {
jquery : "jquery-1.11.1.js"
}
})
```
- module参数
+ id:模块的唯一标识
+ uri: 模块绝对路径
+ dependencies:当前模块依赖
+ exports:当前模块对外接口
### 开闭原则
- 模块拓展一定需要遵守的原则
+ 对添加开放
+ 对修改封闭
### ConmonJS 规范
> CommonJS 规范不是专门为JavaScript模块化制定的规范, <br>
> 而是为JavaScript语言很多在后台没有没有实现的功能制定的API规范 <br>
> 例如:文件操作、网络操作、进程操作等接口API <br>
> 为JavaScript语言本身在后台的功能实现定义了很多API,其中就包括模块化的规范API
- 一个单独的文件就是一个模块
- 所有代码都运行在模块作用域中,不会污染全局作用域
- 每个文件的对外接口是module.exports对象
- require命令用于加载模块文件的接口对象
- 模块可以加载多次,但是只会在第一次加载的时候运行一次,然后运行结果就被缓存了,以后在加载,就直接读取缓存结果
- 模块加载的顺序,按照其在代码中出现的顺序
### CMD、AMD、ConmonJS的区别
- AMD
+ 预加载,预执行
+ 预加载就是把所有的 js 文件模块都下载下来
+ 预执行就是把每个加载成功一个执行一个
- CMD
+ 预加载,懒执行
+ 预加载就是把所有的 js 文件模块都下载下来
+ 懒执行就是等所有的js文件都加载完毕之后了才去执行
- ConmonJS
+ 执行到了哪里,就加载到哪里,然后执行哪里,
+ 同步加载,同步执行