论坛首页 Web前端技术论坛

js闭包的典型应用场景

浏览 11767 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (4) :: 隐藏帖 (4)
作者 正文
   发表时间:2010-01-13  
1. 保护函数的内部变量安全
2. 在内存中维持一个变量,防止被GC

  
 
   function a(){
     var i=0;
     function b(){
       var j=i; //只要是引用了 i 的。
        alert(j);
     }
     return b;
   }

   var c=a(); //a 执行完了,但由于' c();' 的原因 a 的内部变量不会被回收
   c(); //通过c 调用 b 来访问 i (维持 i)
   






   发表时间:2010-01-18  
2. 在内存中维持一个变量,防止被GC

这样的好处是啥呢?
0 请登录后投票
   发表时间:2010-01-18  
顶二楼,这样的好处是啥?为了更容易内存泄漏吗
0 请登录后投票
   发表时间:2010-01-19  
感觉主要还是避免了全局变量和减少了传参,mark一下!
0 请登录后投票
   发表时间:2010-01-19  
闭包的秘密
http://www.gracecode.com/archives/2385/
这篇文章有个PPT讲的得清楚啦。

闭包的作用

1、setTimeout/setInterval
2、回调函数(callback)
3、事件句柄(event handle)

有兴趣的朋友看完可以讨论一下~
0 请登录后投票
   发表时间:2010-01-19  
楼主没说清楚到底是什么应用场景...
“闭包”在编程语言中的意思就是一个函数的所有变量(未列在参数中的变量加上列在参数中的变量)都被绑定并且不可再改变;
那么这个绑定的变量来自于哪里?这是个很重要的问题;
楼主的例子,自由变量是i,i的值是函数内部写死的...其实这算不上“闭包的应用场景”,楼主的例子与以下代码无异:
var c = {'i':0};

闭包其实类似于一个简单的匿名对象,如果仅仅是写死的绑定变量,那么还不如真的去创造一个匿名对象;

但当这些自由变量并非写死,且需要各自变化时,闭包的作用就体现了出来,举个例子:
<input type='button' id='b1'/>
<input type='button' id='b2'/>
<input type='button' id='b3'/>

上面3个button,功能一样——每当被点击,就alert出自己目前为止一共被点击了多少次;
那么这个记录点击次数的变量放在哪里?这3个button的功能完全一样,事件函数可以写成一个,但却需要分别设立变量来存储自己被点击了多少次,那么这个时候闭包的作用就来了:把他们的事件监听函数设置为同一个函数的闭包,这样一来3个button的点击次数就独立变化了,且没有全局变量产生;
就像下面这样的代码:
function genCount(){
    var i = 0;
    return function(){
        i++;
        alert(i);
    }
}
var a = genCount();
var b = genCount();
a();
b();
b();
b();
a();

应该输出1,1,2,3,2,也就是说a和b中的i独立变化
1 请登录后投票
   发表时间:2010-01-19  
我这方面很菜。。
胆怯的问一下,难道js也有GC??
0 请登录后投票
   发表时间:2010-12-30  
我在很多方面都很菜
胆怯的问一句,GC是啥?
0 请登录后投票
   发表时间:2010-12-30  
sudongyuan 写道
我在很多方面都很菜
胆怯的问一句,GC是啥?

垃圾回收,JS引擎有这个功能的,不过没有Java的垃圾回收强大而已。
0 请登录后投票
   发表时间:2011-01-01  
maxm 写道
1. 保护函数的内部变量安全
2. 在内存中维持一个变量,防止被GC

  
 
   function a(){
     var i=0;
     function b(){
       var j=i; //只要是引用了 i 的。
        alert(j);
     }
     return b;
   }

   var c=a(); //a 执行完了,但由于' c();' 的原因 a 的内部变量不会被回收
   c(); //通过c 调用 b 来访问 i (维持 i)
   




楼主的说法有两个小问题。
引用
在内存中维持一个变量,防止被GC

应该是维持函数调用时产生的闭包,防止被GC。维持的是一个闭包对象(一般指执行时上下文),而不是某个变量。

引用
var j=i; //只要是引用了 i 的。

在这里只是赋值,不是引用。也不是因为赋值或引用,闭包才得以保持。
即使没有var j=i;,把下面的alert(j)改为alert(i),也能使闭包不被GC。
实际上,即使没有alert(i),闭包也是不被回收的。
*这里的闭包指的是var c = a();时,调用a所产生的执行时上下文。

每个执行时上下文都有自己的作用域链,用于标识符解析。当执行时上下文被创建时,它的作用域链初始化为当前运行函数的[[scope]]内部属性中所包含的对象。执行时上下文被创建的同时也创建了活动对象,其包含了所有局部变量,命名参数,参数集合,函数声明等。然后这个活动对象被推入作用域链的顶端,为标识符解析服务。

当执行例子中的function a时,function b作为活动对象中的函数声明,其作用域链将包含a的执行时活动对象,就是我们常说的闭包。此时的b又被return到外部,有了外部引用,只要存在外部引用,处在b的作用域链中的a的执行时活动对象将一直存在,不被GC。

至此闭包就被保留了,被保留的原因不是被赋值或被引用,也不是通过c调用b才能维持,调用c只是使用了闭包,不是维持闭包的原因。

  
 
   function a(){
     var i = 100;
     function b(str){
        alert(eval(str));
     }
     return b;
   }

   var c = a(); //a执行后,返回时并没有引用i,闭包依然会被保存。
   c('i'); //仍然能访问闭包。
   
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics