日期:2014-05-16  浏览次数:20401 次

javascript闭包,和使用闭包是程序模块化
本文关于javascript的内容部分借用《javascript语言精粹》这本书!
<html>
<body></body>
</html>
<script>
//使用闭包来隐藏属性
//通过一个函数的形式去初始化myObject该函数返回一个对象字面亮, 定义了一个value变量,
//该变量对increment和getvalue方法都是可用的,但是函数的作用域使得它对其他的程序来说不是可见的
var myObject = function(){
	var value = 2;
	return {
		increment:function(inc){
			value += typeof inc === 'number' ? inc : 1;
			return true;
		},
		getValue:function(){
			return value;
		}
	}
}();
//添加了一个方法 用来测试value是否对get方法可见。
myObject.get = function(){
	return value;
}
//console.log(myObject.getValue());

//使用闭包设定对象的属性为私有属性,
//创建一个名为quo的构造函数
//构造出带有get_status方法和status私有属性的一个对象
var quo = function( status ) {
	return {
		get_status:function(){
			return status;
		}
	};
};
//说明:quo函数设计成无须new来调用, 名字没有首字母大写, 当调用quo的时候 返回包含了get_status方法的一个
//对象 但是get_status 仍然享有访问quo对象的status属性的特权, get_status方法不是访问该参数的一个
//拷贝 它访问的是该参数本身, 因为该函数可以访问它被创建时所处上下文环境, 这被成为闭包。
var myQuo = quo('amazed');
quo('amazed_2');
//属性仅对于myQuo可见
//console.log(myQuo.get_status());

//举例定义一个函数, 它设置一个dom节点为黄色, 然后把它渐变为白色
var fade = function (node) {
	var level = 1;
	var step = function(){
		var hex = level.toString(16);
		node.style.backgroundColor = '#ffff' + hex + hex;
		if(level < 32){
			level += 1;
			setTimeout(step, 100);
		}
	};
	setTimeout(step, 100);
	
}
fade(document.body);

Function.prototype.method = function ( name, func ){
	if( ! this.prototype[name] ){
		this.prototype[name] = func;
	}  
	return this;
}
//2 模块
//添加一个方法, 替换html字符实体为对应的字符
//可以把它放在全局变量中,但是全局变量是一个大锅, 容易混淆,并且出现异常
//可以把它定义为函数本身,但是运行是有损耗,因为每次函数被执行时候该字面量会被求值一次
//理想的方式 将它放入一个闭包
String.method('deentityify', function(){
	var entity = {
		quot:'"',
		lt  : '<',
		gt  : '>'
	};
	return function(){
		return this.replace(/&([^&:]+);/g, function(a,b){
			var r = entity[b];
			return typeof r === 'string' ? r : a;
		});
	}
}());
//注意最后()运算字符 立刻调用刚构造出来的函数,这个调用创建并返回的函数才识deeentityify方法

console.log('test&lt;&quot;test&gt;'.deentityify());
//模块模式的一般形式是:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有
//变量和函数的特权函数,最后返回这个特权函数, 或者把他们保存在一个可访问到的地方
//使用模块可以摒弃全局变量的使用,它能够是信息隐藏, 可用于应用程序的封装 或者构造其他单例对象
//举例2将一个查找数组对应值的方法 闭包,并且放入基本类型,方便使用
Array.method('getArrayKey', function(value){
	return function(value){
		var arrlen = this.length;
		if(arrlen == 0){
			return false;
		}
		for (var i=0; i<arrlen; i++){
			if(this[i]===value){
				return i;
			}
			continue;
		}
	};
}());
var a = [1,2,3,5];
console.log(a.getArrayKey(5));


//模块模式也可以用来产生安全的对象, 

//举例 生成一个序列号的对象
var serial_maker = function(){
	var prefix = '';
	var seq = 0;
	return {
		set_prefix: function(p){
			prefix = String(p);
		},
		set_seq : function(s){
			seq = s;
		},
		gensym : function(){
			var result = prefix + seq;
			seq+=1;
			return result;
		}
	};
};
var seger = serial_maker();
seger.set_prefix("Q");
seger.set_seq(1000);
console.log(seger.seq)//undefined闭包产生的属性是私有属性。 重新构建就会重新生成 ,无法改变
//prefix 和 seq  除非调用对应方法
console.log(seger.gensym())

</script>