掌握模块化基本概念以及使用模块化带来的好处
当你的网站开发越来越复杂的时候,会经常遇到什么问题?
历史上,JavaScript一直没有模块(module)体系, 无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。 其他语言都有这项功能,比如Ruby的 require、Python的 import , 甚至就连CSS都有 @import , 但是JavaScript任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。
如何解决不通过 script 标签就能加载 JavaScript 文件代码。
什么是模块化
使用模块化开发的方式带来的好处
眼见他起高楼,眼见他宴宾客,眼见他楼塌了。
体验刀耕火种的模块化解决方式
以后如果不使用第三方规范的情况下, 如果写模块可以采用下面这种方式
```js ; (function (形参模块名, 依赖项, 依赖项) { // 通过 形参模块名 修改模块
window.模块名 = 形参模块名 })(window.模块名 || {}, 依赖项, 依赖项) ```
下面是一个关于模块化的面试题,一起观察和分析这段代码的作用:
js var UTIL = (function (parent, $) { // 动态的给一个不存在的对象挂载一个子对象 var my = parent.ajax = parent.ajax || {} my.get = function (url, params, callback) { return $.getJSON(url, params, callback) } return parent }(UTIL || {}, jQuery))
自然界生态系统、计算机操作系统、软件办公系统,还有教育系统、金融系统、网络系统、 理论系统等等。究竟什么是系统呢?
维基百科:系统泛指由一群有关连的个体组成,根据预先编排好的规则工作, 能完成个别元件不能单独完成的工作的群体。 系统分为自然系统与人为系统两大类。
简单来说,系统有两个基本特性:
系统之间的个体可以成为系统成员,要构建一个系统,最基本的层面需要做两件事:
Sea.js 是一个适用于 Web 浏览器端的模块加载器。 在 Sea.js 里,一切皆是模块,所有模块协同构建成模块系统。 Sea.js 首要要解决的是模块系统的基本问题:
在前端开发领域,一个模块,可以是JS 模块,也可以是 CSS 模块,或是 Template 等模块。 而 Sea.js 则专注于 JS 文件模块:
把上面两点中提及的基本书写格式和基本交互规则描述清楚,就能构建出一个模块系统。 对书写格式和交互规则的详细描述,就是模块定义规范(Module Definition Specification)。
比如 CommonJS 社区的 Modules 1.1.1 规范, 以及 NodeJS 的 Modules 规范, 还有 RequireJS 提出的 AMD 规范等等。
Sea.js 遵循的是 CMD 规范。
CMD、AMD、CommonJS 都是社区制定出来的模块规范, 他们的目的都是为了解决 JavaScript 没有模块化系统的问题。 他们都有如何定模块成员,以及模块成员之间如何进行通信交互的规则。
AngularJS Module 也是 ng 框架本身提供的一个模块系统解决方案。 ng定义模块需要起名,即便你去加载或者依赖一个模块的时候, 这个被依赖的模块也需要通过 script 标签引入到 html 页面中。
2015 年 9 月份,ECMAScript 官方推出了 ECMAScript 6 语言标准。 在最新的 ES6 语言规范标准中,已经制定了 JavaScript 模块化规范。
export import
前端界的风气:都喜欢追赶新技术,甚至把没有推出来的标准直接干到了生产环境。
这个社区太浮躁了。
A Module Loader for the Web, Enjoy the fun of programming.
关于 SeaJS
为什么学习和使用 SeaJS ?
谁在用?
SeaJS 适用场景
bower install seajsnpm install seajsdefine 函数定义模块require 函数加载模块module.exports 对外暴露接口对象seajs.use 函数启动模块系统seajs.use加载模块,启动模块系统。
seajs.use(‘id‘)seajs.use(‘id‘, callback)加载多个模块,加载完成时,执行回调 seajs.use([‘id1‘,‘id2‘,...],callback)
注意:
DOM ready 事件没有任何关系。如果某些操作要确保在 DOM ready 后执行,需要使用 jquery 等类库来保证define 中的模块代码里define(factory)define 是一个全局函数,用来定义模块。
define 接受 factory 参数,factory 可以是一个函数,也可以是一个对象或字符串。
factory 为对象、字符串时,表示模块的接口就是该对象、字符串。
factory 是一个对象时
define({})factory 是一个字符串时
define(‘hello‘)factory 是一个函数时
define(function(require, exports, module){})requirerequire 用来加载一个 js 文件模块, require 用来获取指定模块的接口对象 module.exports。
require 在加载和执行的时候,js 会按照同步的方式和执行。
使用注意:
必须 命名为 requireTips: 把 require 看做是语法关键字就好啦
模块标识是一个字符串,用来标识模块。
模块标识可以不包含文件后缀名,比如 .js
模块标识可以是 相对 或 顶级 标识
相对标识
相对标识以 . 开头,永远相对于当前模块所处的路径来解析。
顶级标识不以 . 或 / 开始,会相对模块系统的基础路径(base路径,默认是 sea.js 文件所属的路径)。 可以手动配置 base 路径。
js seajs.config({ base: ‘./js‘ })
除了相对和顶级标识之外的标识都是普通路径。 普通路径的解析规则,会相对当前页面解析。
```js // 假设当前页面是 http://example.com/path/to/page/index.html
// 绝对路径是普通路径: require.resolve(‘http://cdn.com/js/a‘); // => http://cdn.com/js/a.js
// 根路径是普通路径: require.resolve(‘/js/b‘); // => http://example.com/js/b.js
// use 中的相对路径始终是普通路径: seajs.use(‘./c‘); // => 加载的是 http://example.com/path/to/page/c.js
seajs.use(‘../d‘); // => 加载的是 http://example.com/path/to/d.js ```
Tips:
base 基础路径解析。
seajs.config({ base: ‘基础路径‘ }) 来配置基础路径seajs.use 中的相对路径始终相对当前页面来解析。module 是一个对象,上面存储了与当前模块相关联的一些属性和方法。
module.id
define 方法的第一个参数来指定,默认为该模块文件的绝对路径module.uri
module.dependencies
module.exports
return module.exportsexports 仅仅是 module.exports 的一个引用。 也就是说修改了 exports 就相当于修改了 module.exports。
但是一旦在 factory 内部给 exports 重新赋值,并不会改变 module.exports 的值。 因此给 exports 赋值是无效的。
module.exportsmodule.exports 或给它赋值改变模块接口对象exports 是 module.exports 的一个引用,就好比在每一个模块定义最开始的地方写了这么一句代码:var exports = module.exports关于这俩哥们儿的区别请分析一下代码:
```js var module = { exports: {} }
function changeExports (exports, module) { // var exports = module.exports exports.foo = ‘bar‘
// 这里赋值拿不到,不要使用使用 // exports = function () {} return module.exports }
changeExports(module.exports, module) ```
那为啥要有 exports ?
为了开发体验,API更友好,使用 exports 的时候,可以少写一个点儿。
如果你实在分不清楚 exports 和 module.exports 之间的区别,就只记得 module.exports 就可以了。
原文:http://www.cnblogs.com/lsy0403/p/5988124.html