Javascript模块化开发(一)——简单的改造

由于 javascript 自身没有命名空间,所以避免命名冲突,使用模块化开发是最好的解决方式。模块化之后的代码具有更好的代码组织方式,利于自己也有自己更好的理解代码,也便于维护。而模块化开发也有很多方法,以下我们一一来说说它们。

对象字面量

最常见的是对象字面量方法,也称 Json 风格,可以理解为名值对组成的散列表(hash table,也叫哈希表)。一个对象被包含在大括号中{}中、以逗号分割的 名称/值 对,名称可以是字符串也可以是标识符,换种说法就是:可以用引号括起来也可以不括。如下:

var myMoudule = {
	myProperty : 1,  // 共享属性
	config     : {
		wrapper : '',
		container : '' 
	},
	init : function(config) {
		this.config = config; //
		console.log(this.config)
	},
	myMethod1  : function () {
		var private_v = '私有变量'; // 私有属性
		this.myProperty = this.myProperty + 4;
		console.log( this.myProperty );
	},
	myMethod2  : function () {
		this.myProperty = this.myProperty - 2;
		console.log( this.myProperty );
		console.log(typeof private_v) // undefined
	}
}
myMoudule.init({wrapper:'id',container:'tagName' }); // Object {wrapper: "id", container: "tagName"} 
myMoudule.myMethod1(); //5
myMoudule.myMethod2(); //3
		
对象字面量 风格模块化

但是字面量风格的模块化却不能优雅的解决 共有/私有方法和变量。

虽然我们可以将共有的属性/方法定义在对象上;私有的属性/方法则定义在共有方法内。但是当当几个共有方法重复调用同一个私有方法,为了避免代码重复,那么每次调用共有属性/方法前面都得加this,而且该属性/方法也不得不暴露出去。而这有违背了我们的本意,所以这不够优雅。而 Module 模式解决这个问题。

Module(模块)模式

而模块模式解决了以上问题,它提供了一种包装 共有/私有方法和变量 优雅的方式。通过该API ,只需返回共有的API,其他都维持在私有闭包内。

下面是一个简单的例子:

var myNamespace = (function(){
	var myPrivateVar = 0; // 私有变量
	var myPrivateMethod = function (foo){  //私有方法
		console.log(foo)
	};
	return { // 要暴露的变量和方法
		myPublicVar : 'foo',  
		myPublicFunction : function(bar) {
			myPrivateVar++;
			myPrivateMethod(bar);
		} 
	}
})();
myNamespace.myPublicFunction(3); // 3
	

跟字面量对象相比的优点就是:能自由、优雅地控制 方法/变量 的暴露还是私有。

var namespce = (function(){ ... })();是将一个对象赋值给变量,所以内部可以使用this引用共有属性/方法。

以上代码可以修改如下,上例可以理解为 return 为一个空对象。

var myNamespace = (function(){
	var pub = {};

	var myPrivateVar = 0;
	pub.myPublicVar = 'foo';

	var myPrivateMethod = function (){
		console.log(pub.myPublicVar)
	};
	pub.myPublicFunction = function(bar) {
		myPrivateVar++;
		myPrivateMethod();
	} 
	return pub
})();
myNamespace.myPublicFunction();
	

这样写的目的更好的区分而共有还是私有,但是每次定义公用属性/方法前面都必须得加个对象名,很烦有没有。所以有了如下改进方法:

var myRevealingModule = function(){
	var privateVal = 'guwei',
		publicVal  = 'hello';
	function privateGetName () {
		console.log ('name:'+privateVal);
	}
	function publicSetName (strname) {
		privateVal = strname;
	}
	function publicGetName () {
		privateGetName();
	}
	return {
		setName : publicSetName,
		getName : publicGetName
	}
}();
myRevealingModule.setName('han');
myRevealingModule.getName(); //name:han 
	

该模式让代码语法更加一致,很容易看出哪些函数和变量是暴露的。

可以拿以上代码再做如下处理:

	var myModule = (function ( jQ ) {
	 
	    function method(){
	        jQ(".container").html("test");
	    }
	 
	    return{
	        publicMethod: function(){
	            method();                
	        }            
	    };
	 
	})( jQuery ); // 告诉使用者此模块依赖 jQuery
	myModule.publicMethod();
	

立即执行函数中可以使用此全局变量的方法,并可以修改(简化)全局变量的名称。

参考以上方法,我们对直接将全局变量定义在 window 上,然后作为参数传入,如下:

		(function(pub){
			var myPrivateVar = 0;
			pub.myPublicVar = 'aoo';

			var myPrivateMethod = function (){
				console.log(myPrivateVar)
			};
			pub.myPublicFunction = function(bar) {
				myPrivateVar++;
				myPrivateMethod();
			} 
		})(window.myModule = window.myModule || {}) // 防止 window.myModule 未定义而导致出错 
	

当然如果不想暴露模块内的任何对象,则在 立即执行函数 里定义函数,并且在 立即执行函数 模块内调用。这样这个模块里的代码不会影响到其他代码,其他代码也不会影响到这里面的代码。

以上通过 对象、闭包、自执行方法 来模块化开发是最常用的方法,几种方法各有秋千。下篇文章介绍 CommonJS规范 和 AMD规范 以及 一些JavaScript模块加载框架。

本文源链接:http://www.html5jscss.com/module-closure-json-iife.html

转载请注明《Javascript模块化开发(一)——简单的改造》| html5jscss

评论关闭了.