浅谈javascript闭包

什么是闭包,各种专业论文上有很多解释,简单是说就是一种能够读取其它函数内部变量的函数,在javascript的高级应用中经常用到,但是JS中只有函数内部的子函数才能读取此函数的变量,因此在JS中的闭包实际上就是函数内部的函数

function f1(){
  var n=999;
  nAdd=function(){n+=1}
  function f2(){
    alert(n);
  }
  return f2;
}

var result=f1();
result(); // 999
nAdd();
result(); // 1000


上面这个例子,f2就是所谓的闭包,他包含在函数f1里面。
闭包最大的用途有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
例如上面的例子中的f2,它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
原因在于,f2被赋给了一个全局变量n(实际上n是f1中的变量,但在f2中并不是传递进来的变量,也未声明,而是读取的上级函数的变量,判定为全局变量),这就导致了f2被一直存在内存中,而f2依赖于f1,因此f1也被存于内存中而不被释放,才导致了后面使用result的时候两次值的增加。
这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。</p>
这是从博客园上看到的一个淘宝前端开发面试JavaScript部分一道题。
题目是:下面这个ul,如何点击每一列的时候alert其index值


<ul id=”test”>

<li>这是第一条</li>

<li>这是第二条</li>

<li>这是第三条</li>

</ul>
<p>

 


使用js遍历很容易就做出来,同时他给出了一种用闭包解决的方法:

var lis_lis = $("test").getElementsByTagName("li");
for (var i = 0, l = lis_lis.length; i < l; i++) {
lis_lis[i].onclick = (function(x) {
return function() {
alert(x);
}
})(i);
}

 

这段代码中lis_lis[i].onclick调用了一个闭包函数,这个闭包函数和之前的例子不同的在于它传值i进去了,这个就要考虑到这个的表达式形式,区别而言是给lis_lis[i].onclick赋值的表达式,而之前的例子是函数声明形式的,用法雷同。
下面贴一些例子:

//*************闭包uniqueID*************
uniqueID = (function(){ //这个函数的调用对象保存值
var id = 0; //这是私有恒久的那个值
//外层函数返回一个有权访问恒久值的嵌套的函数
//那就是我们保存在变量uniqueID里的嵌套函数.
return function(){return id++;}; //返回,自加.
})(); //在定义后调用外层函数. 
document.writeln(uniqueID()); //0
document.writeln(uniqueID()); //1
document.writeln(uniqueID()); //2
document.writeln(uniqueID()); //3
document.writeln(uniqueID()); //4

 

 

//*************闭包阶乘*************
var a = (function(n){
if(n<1){ alert("invalid arguments"); return 0; }
if(n==1){ return 1; }
else{ return n * arguments.callee(n-1); }
})(4);
document.writeln(a);
</pre>
<pre lang='javascript' colla='+'>
function User( properties ) { 
//这里一定要声明一个变量来指向当前的instance 
var objthis = this; 
for ( var i in properties ) { 
(function(){ 
//在闭包内,t每次都是新的,而 properties[i] 的值是for里面的 
var t = properties[i]; 
objthis[ "get" + i ] = function() {return t;}; 
objthis[ "set" + i ] = function(val) {t = val;}; 
})(); 
} 
} 

//测试代码 
var user = new User({ 
name: "Bob", 
age: 44 
}); 

alert( user.getname()); 
alert( user.getage()); 

user.setname("Mike"); 
alert( user.getname()); 
alert( user.getage()); 

user.setage( 22 ); 
alert( user.getname()); 
alert( user.getage());
posted @ 2012-07-30 14:56  Lucien_oblivious  阅读(294)  评论(0)    收藏  举报