JavaScript 模块化编程
来源: 阅读:815 次 日期:2015-04-09 16:35:07
温馨提示: 小编为您整理了“JavaScript 模块化编程”,方便广大网友查阅!

一直对JS都是一知半解,最近遇到这方面问题,所以在网上学习了一下,现在还没有完全明白,先贴出笔记;

第一章 JavaScript模块化编程

(一):模块的写法

一 原始写法

// 模块就是实现特定功能的一组方法;只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块;

function m1(){

// ...

}

function m2(){

// ...

}

// 上面的函数m1()和m2(),组成一个模块;使用时直接调用就行;

// 缺点:"污染"了全局变量; 无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系;

二 对象写法

// 把模块写成一个对象,所有的模块成员都放到这个对象里面;

var module = new Object({

_count:0,

m1:function(){

// ...

},

m2:function(){

// ...

}

});

// 上面的函数m1()和m2(),都封装在module对象里;使用时直接调用这个对象的属性;

module.m1();

// 但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写;

module._count = 4;

三 立即执行函数写法

var module = (function(){

var _count = 0;

var m1 = function(){

// ...

};

var m2 = function(){

};

return {

m1:m1,

m2:m2

};

})();

// 使用上面的写法,外部代码无法读取内部的_count变量;

console.info(module._count); // undefined;

// 上面的写法就是JavaScript模块的基本写法;

四 放大模式

1

2

3

4

5

6

7

8

// 如果模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式";

var module = (function(mod){

mod.m3 = function(){

// ...

};

return mod;

})(module);

// 上面的代码为module模块添加了一个新方法m3(),然后返回新的module模块;

五 宽放大模式

1

2

3

4

5

6

7

// 在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载;

// 如果采用上一节的写法,第一个执行的部分有可能加载一个不存在的空对象,这时就要采用"宽放大模式";

var module = (function(mod){

// ...

return mod;

})(window.module || {});

// 与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象;

六 输入全局变量

1

2

3

4

5

6

7

// 独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互;

// 为了在模块内部调用全局变量,必须显式地将其他变量输入模块;

var module = (function($,YAHOO){

// ...

})(jQuery,YAHOO);

// 上面的module模块需要使用jQuery库和YUI库,就把这两个库(其实是两个模块)当作参数输入module;

// 这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显;

第二章 JavaScript模块化编程(二):AMD规范

一 模块的规范

// 目前,通行的JavaScript模块规范共有两种:CommonJS和AMD;

二 CommonJS

// node.js将javascript语言用于服务器端编程,这标志"JavaScript模块化编程"正式诞生;

// node.js的模块系统,就是参照CommonJS规范实现的;

在CommonJS中,有一个全局性方法require(),用于加载模块;

var math = require('math'); // 加载模块;

math.add(2,3); // 调用模块方法=>5;

三 浏览器环境

// 上一节的代码在浏览器中运行会有很大的问题;

var math = require('math');

math.add(2,3);

// 问题:必须在require('math')等math.js加载完成,才会执行math.add(2,3);

// 所以浏览器的模块,不能采用"同步加载",只能采用"异步加载";==>AMD;

四 AMD

AMD(Asynchronous Module Definition)异步模块定义;

// 采用异步加载模块,模块的加载不影响它后面语句的运行,所有依赖这个模块的语句,都定义在一个回调函数中,

// 等加载完成之后,这个回调函数才会运行;

// AMD也采用require()语句加载模块,但是它要求两个参数:

require([module],callback);

// module:是一个数组,里面的成员就是要加载的模块;

// callback:是加载成功之后的回调函数;

require(['math'],function(math){

math.add(2,3);

});

// math.add()与math模块加载不是同步的,浏览器不会发生假死;所以,AMD比较适合浏览器环境;

第三章 JavaScript模块化编程(三):require.js的用法

一 为什么使用require.js

// 需要依次加载多个js文件;

// 缺点:

// 1.加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;

// 2.由于js文件之间存在依赖关系,因此必须严格保证加载顺序,当依赖关系很复杂的时候,代码的编写和维护都会变得困难;

// 所以require.js解决了这两个问题:

// 1.实现js文件的异步加载,避免网页失去响应;

// 2.管理模块之间的依赖性,便于代码的编写和维护;

二 require.js的加载

1.加载require.js

<script scr="js/require.js" defer async="true"></script>

// async属性表明这个文件需要异步加载,避免网页失去响应;IE不支持这个属性,只支持defer,所以把defer也写上;

2.加载main.js

<script src="js/require.js" data-main="js/main"></script>

// data-main属性的作用是,指定网页程序的主模块=>main.js,这个文件会第一个被require.js加载;

// 由于require.js默认的文件后缀名是js,所以可以把main.js简写成main;

三 主模块main.js的写法

1.如果main.js不依赖任何其他模块,可以直接写入JavaScript代码;

// main.js

alert('加载成功!');

2.如果main.js依赖于模块,这时就要使用AMD规范定义的require()函数;

// main.js

require(['moduleA','moduleB','moduleC'],function(moduleA,moduleB,moduleC){

// ...

})

// require()函数接收两个参数:

// 参数一:数组,表示所依赖的模块,即主模块依赖的三个模块;

// 参数二:回调函数,当前面指定的模块都加载成功后,它将被调用;加载的模块会以参数形式传入该函数,从而在回调函数内部可以使用这些模块;

// require()异步加载模块,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题;

实例:

require(['jquery','underscore','backbone'],function($,_,Backbone){

// ...

});

四 模块的加载

// 使用require.config()方法,可以对模块的加载行为进行自定义;

// require.config()就写在主模块(main.js)的头部;

// 参数就是一个对象,这个对象的paths属性指定各个模块的加载路径;

// 设定以下三个模块的文件默认和main.js在用一个目录;

require.config({

paths:{

"jquery":"jquery.min",

"underscore":"underscore.min",

"backbone":"backbone.min"

}

});

// 如果加载的模块和主模块不在同一个目录,就要逐一指定路径;

require.config({

paths:{

"jquery":"lib/jquery.min",

"underscore":"lib/underscore.min",

"backbone":"lib/backbone.min"

}

});

// 或者直接改变基目录(baseUrl)

require.config({

baseUrl:"js/lib",

paths:{

"jquery":"jquery.min",

"underscore":"underscore.min",

"backbone":"backbone.min"

}

});

// 如果模块在另一台主机上,也可以直接指定它的网址

require.config({

paths:{

"jquery":""

}

});

// require.js要求,每个模块是一个单独的js文件;这样的话,如果加载多个模块,就会发出多次HTTP请求,会影响网页的加载速度;

// 因此,require.js提供了一个优化工具,当模块部署完毕以后,可以用这个工具将多个模块合并在一个文件中,减少HTTP请求数;

五 AMD模块的写法

// require.js加载的模块,采用AMD规范,也就是说,模块必须按照AMD的规定来写;

// 具体来说,就是模块必须采用特定的define()函数来定义;如果一个模块不依赖其他模块,那么可以直接定义在define()函数中;

// 在math.js中定义math模块

// math.js

define(function(){

var add = function(x,y){

return x+y;

};

return {

add:add

};

});

// 在main.js中加载math模块

require(['math'],function(math){

alert(math.add(1,1));

});

// 如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性;

// math.js

define(['myLib'],function(myLib){

function foo(){

myLib.doSomething();

}

return {

foo:foo

};

});

// 当require()函数加载上面这个模块的时候,就会先加载myLib.js文件;

六 加载非规范的模块

// 加载非规范的模块,在用require()加载之前,要先用require.config()方法,定义它们的一些特征;

require.config({

shim:{

'underscore':{

exports:'_'

},

'backbone':{

deps:['underscore','jquery'],

exports:'Backbone'

}

}

});

// require.config()接收一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块;

// (1).定义deps数组,表明该模块的依赖性;

// (2).定义exports值(输出的变量名),表明这个模块外部调用时的名称;

比如:jQuery的插件

shim:{

'jquery.scroll':{

deps:['jquery'],

exports:'jQuery.fn.scroll'

}

};

七 require.js插件

1.domready:可以让回调函数在页面DOM结构加载完成之后运行;

require(['domready!'],function(doc){

// called once the DOM is ready;

})

2.text和image:允许require.js加载文本和图片文件;

define(['text!review.txt','image!cat.jpg'],function(review,cat){

console.log(review);

document.body.appendChild(cat);

});

更多信息请查看IT技术专栏

更多信息请查看脚本栏目
手机网站地址:JavaScript 模块化编程
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:hfpxwx
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map