JS闭包访问外部变量解决实例

JavaScript 2012-08-01 JavaScript,闭包,变量

闭包是指有权访问另一个函数作用域中的变量的函数,但作用域的配置机制有一个需要注意的地方,即闭包只能取得包含函数中任何变量的最后一个值。

如以下案例:

function create(){
	var arr = new Array();	

	for (var i=0; i<10; i++){
		arr[i] = function(){
			return i;
		};	
	}

	return arr;
}

var c_arr = create();

for(var i=0; i<c_arr.length;i++){
	document.write("c_arr["+i+"] = "+c_arr[i]()+"<br />");	
}

执行结果:

JS闭包

表面上看,似乎每个函数返回的i值都不相同,比如c_arr[0]的值应该是0,c_arr[1]的值应该是1,以此类推。可结果每个函数都返回10。为什么呢?

因为每个函数的作用域链中保存着create()函数的活动对象,所以它们引用的都是同一个变量i。当for循环结束以后,i的值也就变成10了,此时每个函数都引用保存变量i的同一个变量对象。

 

我们可以通过创建另一个域名函数强制让闭包的行为符合预期,使每个位置对应相应的值。

function create(){
	var arr = new Array();	

	for (var i=0; i<10; i++){
		arr[i] = function(num){
			return function(){
				return num;	
			};
		}(i);	
	}

	return arr;
}

var c_arr = create();

for(var i=0; i<c_arr.length;i++){
	document.write("c_arr["+i+"] = "+c_arr[i]()+"<br />");	
}

执行结果:

JS闭包

定义了一个匿名函数,并立即执行匿名函数的机过赋给数组,这里匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个函数时我们传入变量i。由于函数参数是按值传递的,所以就会将变量i的当前值赋值给参数num。而在这个匿名函数内部,又创建并返回了一个访问num的闭包,这样一来arr数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了。

经典例子

我们再来看一个经典的例子,假设页面有一组button标签,我们利用脚本给这组button标签绑定单击事件,并且单击时能弹出这是第几个标签。

<meta charset="utf-8" />

<button>第一个</button>
<button>第二个</button>
<button>第三个</button>
<button>第四个</button>


<script type="text/javascript">

var obj = document.getElementsByTagName('button');
for(var i=0;i<obj.length;i++){
	obj[i].onclick = function(){
		alert(i);
	};	
}

</script>

点击每一个按钮结果

JS闭包

表面上看,似乎单击每一个标签应该弹出不同数字

第一个应该弹出0;

第二个应该弹出1;

以此类推。

可结果是所有按钮都弹出4,显然这不是我们想要的结果。

我们把程序改一下

<meta charset="utf-8" />

<button>第一个</button>
<button>第二个</button>
<button>第三个</button>
<button>第四个</button>


<script type="text/javascript">

var obj = document.getElementsByTagName('button');
for(var i=0;i<obj.length;i++){
	obj[i].onclick = function(num){
		return function(){
			alert(num);
		}		
	}(i);		
}

</script>

点击第二个

JS闭包

点击第四个

JS闭包

我们只需要在函数内建立一个匿名函数,同以上案例同理。即可实现匿名函数捕获外部变量i,结果每个按钮弹的i值都不同。

文字链接:《JS闭包访问外部变量解决实例

文章地址:http://www.qttc.net/201208154.html

除非标注,琼台博客所有博文均为原创,转载请加文字链接注明来源

乳名?小名?昵称?网名?均可

email,放心,我不会给你乱投广告的

想获得回访就把你的站点URL写上(没有留空)

[NOTICE]木要投放广告
[NOTICE]木要骂人,说不该说的话
[NOTICE]自由言论,但要遵纪守法

Comments 0

    Hi,你想第一个做沙发么?