• JavaScript中闭包之浅析解读


        JavaScript中的闭包真心是一个老生常谈的问题了,,其实我们在做项目时候,其实就经常用到闭包的,可是面试问的时候,回答又往往是我们经常搜到的答案,唉 不管是应付面试 还是真的想学点东西 ,我也用自己的理解跟大家分享一下,书面化就避免不了了的。

      1.闭包是什么?

      红宝书中曰:“是指有权访问另外一个函数作用域中的变量的函数。”

      简单的说,JavaScript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。再通俗的说就是“一个函数内部创建另外一个函数,后面这个函数可以读取上面那个函数中的变量,后面这个函数就可以称作‘闭包’”。

      2.闭包有啥用?

      通过我大量的查阅,如果说“通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率”,会不会感觉很空洞,那这些会不会好一些,由于在JavaScript中没有真正的块级作用域,但是为了给某个函数声明一些只有该函数才能使用的局部变量时,我们就会用到闭包,这样我们可以很大程度上减少全局作用域中的变量,净化全局作用域

       下面举例说明一下:

        1.匿名自执行函数

           我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,

          比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。
          除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,
          比如UI的初始化,那么我们可以使用闭包:
     
          
    var data= {    
        table : [],    
        tree : {}    
    };    
         
    (function(dm){    
        for(var i = 0; i < dm.table.rows; i++){    
           var row = dm.table.rows[i];    
           for(var j = 0; j < row.cells; i++){    
               drawCell(i, j);    
           }    
        }    
           
    })(data);   

    我们创建了一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在函数执行完后会立刻释放资源,关键是不污染全局对象。

      2.结果缓存

      我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。

      

    var CachedSearchBox = (function(){    
        var cache = {},    
           count = [];    
        return {    
           attachSearchBox : function(dsid){    
               if(dsid in cache){//如果结果在缓存中    
                  return cache[dsid];//直接返回缓存中的对象    
               }    
               var fsb = new uikit.webctrl.SearchBox(dsid);//新建    
               cache[dsid] = fsb;//更新缓存    
               if(count.length > 100){//保正缓存的大小<=100    
                  delete cache[count.shift()];    
               }    
               return fsb;          
           },    
         
           clearSearchBox : function(dsid){    
               if(dsid in cache){    
                  cache[dsid].clearSelection();      
               }    
           }    
        };    
    })();    
         
    CachedSearchBox.attachSearchBox("input");    

    这样我们在第二次调用的时候,就会从缓存中读取到该对象。

      3.封装

    var person = function(){    
        //变量作用域为函数内部,外部无法访问    
        var name = "default";       
           
        return {    
           getName : function(){    
               return name;    
           },    
           setName : function(newName){    
               name = newName;    
           }    
        }    
    }();    
         
    print(person.name);//直接访问,结果为undefined    
    print(person.getName());    
    person.setName("abruzzi");    
    print(person.getName());    

    4.实现类和继承

    function Person(){    
        var name = "default";       
           
        return {    
           getName : function(){    
               return name;    
           },    
           setName : function(newName){    
               name = newName;    
           }    
        }    
        };   
     
        var p = new Person();
        p.setName("Tom");
        alert(p.getName());
     
        var Jack = function(){};
        //继承自Person
        Jack.prototype = new Person();
        //添加私有方法
        Jack.prototype.Say = function(){
            alert("Hello,my name is Jack");
        };
        var j = new Jack();
        j.setName("Jack");
        j.Say();
        alert(j.getName());

    写到最后,不知道最后各位亲们发现  自己曾经做过的项目中其实用到过很多这种,反正我是遇到了,闭包就是这么一直存在着的。

    关于闭包,虽然老生常谈,但是还是挺重要的。至于闭包的缺陷嘛,就说一个好了 不是干货  滥用闭包 ,会导致内存泄漏,内存泄漏是啥 自己百度吧 ^_^。

    谢谢各位道友能看到最后,希望大家都能顺顺心心。

  • 相关阅读:
    [再寄小读者之数学篇](2014-05-27 偏导数的计算)
    [再寄小读者之数学篇](2014-05-27 积分估计)
    [再寄小读者之数学篇](2014-05-27 二阶矩阵的不等式)
    [再寄小读者之数学篇](2014-05-27 特征值估计)
    [家里蹲大学数学杂志]第039期高等数学习题集
    [家里蹲大学数学杂志]第038期历史上最伟大的10个方程
    [家里蹲大学数学杂志]第037期泛函分析期末试题
    [再寄小读者之数学篇](2014-05-26 计算行列式)
    [家里蹲大学数学杂志]第036期泛函分析期末试题
    [再寄小读者之数学篇](2014-05-25 矩阵的交换子)
  • 原文地址:https://www.cnblogs.com/fangshidaima/p/5804120.html
Copyright © 2020-2023  润新知