zoukankan      html  css  js  c++  java
  • 闭包

    如果别人已经有更好的东西我们为什么不用呢,人类之所以可以从石器时代发展到现在的信息时代呢,不就是因为我们善于学习使用别人总结的经验么,不要辜负了前辈---

    转载:勇敢的心的js之匿名函数

    请先查看http://blog.sina.com.cn/s/blog_912389e5010120n2.html

    这篇博客讲的非常之好,有以下两点思考

    匿名函数中的this

    function fn(){

    var e=(function(){

        return this;

    })();

    return e; }

    fn();

    匿名函数中的变量的话,先找本函数中的,然后找上一层中的,最后找全局的,但是this直接找全局的去了,我们在使用jquery的方法的时候有时间函数中的this也指向了全局,所以我们一般用_self=this;或self=this来保存数据。

    还有一种类似的匿名函数

     document.getElementById('a').onclick = function(){

        alert(this.innerHTML)

       };

    不过这个已经不是匿名函数了,他的this不指向windows.

    还有一种数组不是数组,是类数组。

     看完了后以下几点需要注意的:

    -----------------------------------------------------------------------------------------------------------------------------

    函数声明:
    function functionName(arg0,arg1){
       //函数体
    }
    函数表达式:
    var functionName = function(arg0,arg1){
       //函数体
    }
    函数声明和函数表达式之间的主要区别是前者会在代码执行前被加载到作用域中,而后者是在代码执行到那一行的时候才会有定义。
    另一个区别是函数声明会给函数指定一个名字,而函数表达式则创建一个匿名函数,然后将这个函数赋给一个变量
    --------------------------------------------------------------------------------------------------------------------------------
    1 递归
    递归函数是在一个函数通过名字调用自身的情况下构成的,例如:
    function factorial(num){
       if (num<=1){
         return 1;
       }
       else{
          return num*factorial(num-1);
       }
    }
    上面这个经典的递归阶乘函数表面看来没有问题,但下面的代码却可能导致它出错:
       var anotherFactorial = factorial;
       factorial = null;
       alert(anotherFactorial(4));   //出错
    以上代码先把factorial()函数保存在变量anotherFactorial中,然后将factorial变量设置为null,结果指向原始函数的引用只剩下一个。但在接下来调用anotherFactorial()时,由于必须执行factorial(),而factorial已经不再是函数,所以就会导致错误。这种情况下使用arguments.callee可以解决这个问题。
    -----------------------------------------------------------------------------------------------------
    闭包和变量
    作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。因为闭包保存的是整个变量对象,而不是某个特殊的变量。
    function createFunctions(){
        var result = new Array();
        for (var i=0;i<10;i++){
          result[i] = function(){return i;}
       }
        return result;
    }
    var funcs = createFunctions();
    for (var i=0;i<funcs.length;i++){
        document.write(funcs[i]()+"<br/>");
    }
    会输出10个10
    这可能通过将第一个for循环中的代码更改为如下代码来修正:
    result[i] = function(num){
         return function(){
            return num;
        }
    }(i);
    ----------------------------------------------------------------------------------------------------------------------
    内存泄漏
    由于IE对JScript对象和COM对象使用不同的垃圾收集例程,因此闭包在IE中会导致一些问题。具体来说,若闭包作用域链中保存着一个HTML元素,就意味着该元素将无法被销毁:
    function assignHandler(){
        var element = document.getElementByIdx_x_x_x_x_x_x_x_x('someElement');
        element.onclick = function(){
           alert(element.id);
       }
    }
    以上代码创建了一个作为element元素事件处理程序的闭包,而这个闭包创建了一个循环引用。因为匿名函数保存了一个对assignHandler()的活动对象的引用,因此就会导致无法减少element的引用数。只要匿名函数存在,element的引用数至少为1,因此它所占用的内存永远不会被回收。但可修改如下:
    function assignHandler(){
        var element = document.getElementByIdx_x_x_x_x_x_x_x_x('someElement');
        var id = element.id;
        element.onclick = function(){
            alert(id);
       }
        element = null;
    }
    上面的代码中,把element.id副本保存在一个变量中,且在闭包中引用该变量消除了循环引用。但这还不够解决内存泄漏,因为闭包会引用包含函数的整个活动对象,而其中包含着element。即使闭包不直接引用element,包含函数的活动对象中也仍然会保存一个引用。因此有必要把element变量设置为null。这样就能够解除对DOM对象的引用,顺利地减少其引用数,确保正常回收其占用的内存。
    --------------------------------------------------------------------------------
    至于闭包模仿块级作用域和私有变量就自己看了
    这个编程的模式我们应该多使用
    var singleton = function(){
         var privateVariable = 0;
         function privateFunction(){return false;}
         //特权/公有方法和属性
         return {
               publicProperty:true,
               return privateFunction();
         }
    }();
    单例模式的学习:
    适合那些单例必须是某种类型的实例,同时还须添加某些属性和方法对其加以增强的情况。如若上例中application对象须是BaseComponent的实例,则可用以下代码:
    var application=function(){
        var components = new Array();
        components.push(new BaseComponent());
        var app = new BaseComponent();
        app.getComponentCount = function(){
           return components.length;
         }
        app.registerComponent = function(component){
           if(typeof component == 'object'){
               components.push(component);
           }
        }
        return app;
    }();
    -----------------------------------------------------------
    后来的补充:
    循环中的闭包:和前面的重复了。

    闭包开始实现累加。
    function box(){
    var age=100;
    return function(){
    age++;
    return age;
    }
    }
    var b=box() ;
    alert(b());
    alert(b());
    ===========================================
    循环中的闭包:
    function box(){
    var arr=[];
    for(var i=0;i<5;i++){
    arr[i]=function(){
    return i;
    };
    }
    return arr;
    }
    var b=box();
    alert(b.length);
    for(var i=0;i<b.length;i++){
    alert(b[i]);
    }
    =====================================
    function box(){
    var arr=[];
    for(var i=0;i<5;i++){
    arr[i]=(function (num){
    return num;
    })(i);
    }
    return arr;
    }
    var b=box();
    for(var i=0;i>b.length;i++){
    alert(b[i]);
    }
    //这里返回的是数组而不是函数了。
    ====================================
    function box(){
    var arr=[];
    for(var i=0;i<5;i++){
    arr[i]=(function (num){
    return function(){rerun num;}
    })(i);
    }
    return arr;
    }
    var b=box();
    for(var i=0;i<b.length;i++){
    alert(b[i]());
    }
    //这里在群里打印出啦的就是0--5.

     
  • 相关阅读:
    QButtonGroup按钮组
    命令链接按钮QCommandLinkButton
    Arduino-常用指令
    第十章第三节 物体的浮沉条件及应用
    安装包制作工具 SetupFactory使用1 详解
    ONVIF、RTSP/RTP、FFMPEG的开发实录
    ffmpeg摄像头采集h264编码RTP发送
    ffmpeg综合应用示例(一)——摄像头直播
    利用ffmpeg一步一步编程实现摄像头采集编码推流直播系统
    ffmpeg超详细综合教程——摄像头直播
  • 原文地址:https://www.cnblogs.com/coding4/p/5445920.html
Copyright © 2011-2022 走看看