Javascript 模块模式

假设现在我们有一个小型的Js库,目的是用来增加一个数字:

var jspy = {
	count: 0,

	incrementCount: function(){
		this.count++;
	},

	decrementCount: function(){
		this.count--;
	},

	getCount: function(){
		return this.count;
	}
};

但是,使用这个js库的人可以用jspy.count = 5的方法来改变这个值。并不是我们的最初目的。在其他的编程语言中你可以定义一个私有变量,但是Javascript并不能“真正”定义私有变量。然而,我们可以通过操作Javascript来实现,这就引出了一个最流行的Javascript设计模式,模块模式

针对上面问题的解决方案如下:

var jspy = (function(){
	var _count = 0;

	var incrementCount = function(){
		_count++;
	}

	var getCount = function(){
		return _count;
	}

	return {
		incrementCount : incrementCount,
		getCount : getCount
	};
})();

首先我们创造一个_count变量,下划线表明它是一个私有变量。再Javascript中下划线并没有什么实际的意义,但是它是一个用来标明私有变量的普遍用法。现在函数就可以操纵、返回变量了:

然而,你注意到了我吧整个库包含在了一个自调用匿名函数中。这是一个在执行过程中马上被执行的函数。这个函数运行,定义了函数和变量然后到了return {}的部分,它告诉函数将其返回给变量jspy,或者换句话说,暴露给用户。我们暴露两个函数而不是_count变量,这意味着我们可以做如下操作:

jspy.incrementCount();
jspy.getCount();

但是当我们试图进行如下操作时:

jspy._count; // undefined

它返回undefined。

对于上面的这种设计模式有许多不同的实现方法。有人喜欢在return 中定义函数:

var jspy = (function(){
	var _count = 0;

	return {
		incrementCount : function(){
			_count++;
		},
		getCount : function(){
			return _count;
		}
	}
})();

受到上面例子的启发,CHristian Heilmann提出了Revealing Module Pattern。他的方法是将所有方法定义为私有变量,也就是说,不在return中定义,但是在那里暴露给用户,如下所示:

var jspy = (function(){
	var _count = 0;
	var incrementCount = function(){
		_count++;
	}
	var resetCount = function(){
		_count = 0;
	}
	var getCount = function(){
		return _count;
	}
	return {
		add : incrementCount,
		reset : incrementCount,
		get : getCount
	};
})();

这种设计模式有两个好处:

  • 首先,它使我们更容易的了解暴露的函数。当你不在return中定义函数时,我们能轻松的了解到每一行就是一个暴露的函数,这时我们阅读代码更加轻松。
  • 其次,你可以用简短的名字(例如add)来暴露函数,但在定义的时候仍然可以使用冗余的定义方法(例如incrementCount)。

原文:《The JavaScript Module Pattern

译者:卓文理

如需转载烦请注明出处:www.zwlme.com