javascript模块化化编程

一:javascript模块化化编程

javascript起初不是一种模块化编程语言,不支持类(class),也不支持模块(module),但是随着业务的发展,javascript也实现了一些“某模块”的效果,ES6中已经支持“类”和“模块”

javascript模块化编程经历了以下几个阶段:

1:函数式写法

模块就是实现特定功能的一组方法

创建文件m.js:

function m1(){...}
function m2(){...}
m1();
m2();

优点:

简单明了
编写方便

缺点:

污染了全局变量
容易与其他模块的变量名冲突
模块内成员之间没有直接联系

2:对象写法

var module = {
	_count:0,
	m1:function(){...},
	m2:function(){...}
}

module.m1();
module.m2();

优点:

解决了函数式写法的缺点

缺点:

模块成员暴露
模块内部变量容易被修改,eg:module._count=1

3:立即执行函数

var module = (function(){
	var _count = 0;
	var m1 = function(){...}
	var m2 = function(){...}
	return {
		m1:m1,
		m2:m2
	}
})()

优点:

不暴露私有成员
外部代码无法访问内部变量

4:继承式写法

是对立即执行函数的加工处理

运行:

var module1 = (function(){
var _count = 0;
var m1 = function(){console.log("m1")};
var m2 = function(){console.log("m2")};
return {
    m1:m1,
    m2:m2
}
})();

var module1 = (function(mod){
    mod.m3 = function(){console.log("m3")};
    return mod;
})(module1);

module1.m1();
module1.m2();
module1.m3();

输出:

m1
m2
m3

运行:

var module1 = (function(){
var _count = 0;
var m1 = function(){console.log("m1")};
var m2 = function(){console.log("m2")};
return {
    m1:m1,
    m2:m2
}
})();

var module2 = (function(mod){
    mod.m3 = function(){console.log("m3")};
    return mod;
})(module1);

module1.m1();
module1.m2();
module1.m3();

module2.m1();
module2.m2();
module2.m3();

输出:

m1
m2
m3
m1
m2
m3

优点:

模块之间实现了继承

缺点:

立即执行函数的参数不可以为空对象

5:继承式兼容写法

var module1 = (function(){
    var _count = 0;
    var m1 = function(){console.log("m1")};
    var m2 = function(){console.log("m2")};
    return {
        m1:m1,
        m2:m2
    }
})();

var module2 = (function(mod){
    mod.m3 = function(){console.log("m3")};
    return mod;
})(module || {});

module1.m1();
module1.m2();
module2.m3();

输出:

m1
m2
m3

优点:

立即执行函数的对象可以是空对象{}

6:调用全局变量

在模块内部调用全局变量,必须显式地将其他变量输入模块。保证了模块的独立性,使得模块之间的依赖关系变得明

var module = (function($){
	...
})(jQuery)

7:总结

立即执行函数有两种写法

(function(){console.log("run1")})();
(function(){console.log("run2")}());
var run3= function(){console.log("run3")}();
var run4= function(){console.log("run4")};

输出:

run1
run2
run3

以下写法是错误的:

function(){console.log("run3")}()

注:最好加上分号运行,否则有可能会语法报错

分析自调用匿名函数

通过定义一个匿名函数,创建一个私有空间,在该空间内定义的变量和方法,外面是访问不了的,应此不会破坏全局命名空间

(function(){console.log("run1")})();

上面这种写法是用第一个括号定义了一个匿名函数,第二个括号执行这个匿名函数,所以会输出run1

(function(){console.log("run2")}());

上面这种写法用外面那个括号强制执行里面的匿名函数

上面两种写法语法上都是对的,二者功能一样,只是运算过程不一样

以上几种写法是传统的js模块写法,模块的好处不言而喻,不过多人开发,必须执行一套规则才能工作,因此出现了CommonJS、AMD以及CMD

8:CommonJS

CommonJS是服务器端的模块化规范,node.js使这个规范的实现,require是用于加载模块,exports是用来定义模块

exports.add = function(){consoe.log("add")}
var add = require("add").add
add()

在上面代码中,是同步加载,由于服务器端不需要网络请求,读取时间很快,因此可以,但是在浏览器端,由于网络等原因,如果采用同步加载,就会造成浏览器会等待很长时间,因此浏览器不能采用CommonJS规范,只能采用异步加载,因此诞生了AMD和CMD

9:AMD

AMD:Asynchronous Module Definition,异步模块定义,采用异步方式加载模块,因此模块的加载不会影响后面语句的运行。所有依赖加载模块的的语句,都定义在一个回调函数中,只有等模块加载完毕,回调函数才会运行,依赖模块的语句才会运行

模块化的好处:

  • 异步加载避免网页失去响应
  • 实现了模块之间的依赖性,便于维护

AMD也采用require加载模块

语法;

require([module1,module2,...],function(module1,module2){})

define([module1,module2,...],function(module1,module2){})

实现了AMD规范的js是require.js

AMD是提前执行,依赖前置

10:CMD

CMD:Common Module Definition,通用模块定义

语法:

define(function(require,exports,module){
	//模块代码
})

实现了CMD规范的js是sea.js

CND是延迟执行,依赖就近

11:require.js

语法:

放在页面底部

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

放在页面顶部

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

放在页面顶部,ie

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

main.js:

require.config({
	baseUrl: "js/lib",
	paths: {
		"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min",
		"underscore": "underscore.min",
		"backbone": "backbone.min"
	},
	shim: {
		'underscore':{
			exports: '_'
		},
		'backbone': {
			deps: ['underscore', 'jquery'],
			exports: 'Backbone'
		}
	}
});

require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
	//some code here
});

模块的定义1:

//math.js

define(function(){
	var add = function(){
		var sum = 0,
        i = 0,
        args = arguments,
        len = args.length;
	    while (i < len){
	        sum += args[i++]
	    }
	    return {
			sum:sum
		};
	}
})

模块的定义2:

define(["module"],function(module){
	function foo(){
		module.do();
	}
	return {
		foo:foo
	}
})

加载此模块

//main.js

require(["math"],function(math){
	console.log(math.add(1,2,3))
})
posted on 2016-05-08 12:23  借个火点烟  阅读(192)  评论(0编辑  收藏  举报