js闭包的用途详解


Posted in Javascript onNovember 09, 2014

我们来看看闭包的用途。事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。

1 匿名自执行函数

我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,
比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。
除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,
比如UI的初始化,那么我们可以使用闭包:

var datamodel = {    

    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);    

       }    

    }    

       

    //build dm.tree      

})(datamodel);  

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

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("input1");   

这样,当我们第二次调用CachedSearchBox.attachSerachBox(“input1”)的时候,
我们就可以从缓存中取道该对象,而不用再去创建一个新的searchbox对象。

3 实现封装

可以先来看一个关于封装的例子,在person之外的地方无法访问其内部的变量,而通过提供闭包的形式来访问:

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());   

得到结果如下: 
  
undefined 
default 
abruzzi 
 
4 闭包的另一个重要用途是实现面向对象中的对象,传统的对象语言都提供类的模板机制,
这样不同的对象(类的实例)拥有独立的成员及状态,互不干涉。虽然JavaScript中没有类这样的机制,但是通过使用闭包,
我们可以模拟出这样的机制。还是以上边的例子来讲:

function Person(){    

    var name = "default";       

       

    return {    

       getName : function(){    

           return name;    

       },    

       setName : function(newName){    

           name = newName;    

       }    

    }    

};    

     

     

var john = Person();    

print(john.getName());    

john.setName("john");    

print(john.getName());    

     

var jack = Person();    

print(jack.getName());    

jack.setName("jack");    

print(jack.getName());   

运行结果如下: 
  
default 
john 
default 
jack 
由此代码可知,john和jack都可以称为是Person这个类的实例,因为这两个实例对name这个成员的访问是独立的,互不影响的。

以上便是js闭包的作用了,非常简单易懂吧,希望对小伙伴们有所帮助

Javascript 相关文章推荐
Jquery操作radio的简单实例
Jan 06 Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
Apr 13 Javascript
微信小程序 基础组件与导航组件详细介绍
Feb 21 Javascript
老生常谈javascript中逻辑运算符&amp;&amp;和||的返回值问题
Apr 13 Javascript
Angularjs为ng-click事件传递参数
Jun 15 Javascript
Vue中的数据监听和数据交互案例解析
Jul 12 Javascript
vue.js 获取select中的value实例
Mar 01 Javascript
小程序异步问题之多个网络请求依次执行并依次收集请求结果
May 05 Javascript
javascript实现图片轮播代码
Jul 09 Javascript
vue 验证码界面实现点击后标灰并设置div按钮不可点击状态
Oct 28 Javascript
vue实现在进行增删改操作后刷新页面
Aug 05 Javascript
js将日期格式转换为YYYY-MM-DD HH:MM:SS
Sep 18 Javascript
js闭包实例汇总
Nov 09 #Javascript
浅谈JS闭包中的循环绑定处理程序
Nov 09 #Javascript
jQuery函数map()和each()介绍及异同点分析
Nov 08 #Javascript
js跨域问题浅析及解决方法优缺点对比
Nov 08 #Javascript
js 操作符汇总
Nov 08 #Javascript
jquery的总体架构分析及实现示例详解
Nov 08 #Javascript
jquery常用方法及使用示例汇总
Nov 08 #Javascript
You might like
无线电的诞生过程
2021/03/01 无线电
php报表之jpgraph柱状图实例代码
2011/08/22 PHP
利用PHP生成静态HTML文档的原理
2012/10/29 PHP
PHP提示Cannot modify header information - headers already sent by解决方法
2014/09/22 PHP
php实现对象克隆的方法
2015/06/20 PHP
php脚本运行时的超时机制详解
2016/02/17 PHP
Yii2中多表关联查询hasOne hasMany的方法
2017/02/15 PHP
js类中获取外部函数名的方法
2007/08/19 Javascript
jquery.validate使用攻略 第二部
2010/07/01 Javascript
jQuery的DOM操作之删除节点示例
2014/01/03 Javascript
使用delegate方法为一个tr标签加一个链接
2014/06/27 Javascript
node.js中的fs.realpath方法使用说明
2014/12/16 Javascript
Javascript 多物体运动的实现
2014/12/24 Javascript
jQuery插件Zclip实现完美兼容个浏览器点击复制内容到剪贴板
2015/04/30 Javascript
浅谈Javascript实现继承的方法
2015/07/06 Javascript
jQuery基于toggle实现click触发DIV的显示与隐藏问题分析
2016/06/12 Javascript
angularJS之$http:与服务器交互示例
2017/03/17 Javascript
《javascript少儿编程》location术语总结
2018/05/27 Javascript
vue实现动态显示与隐藏底部导航的方法分析
2019/02/11 Javascript
javascript中call,apply,callee,caller用法实例分析
2019/07/24 Javascript
Vue中错误图片的处理的实现代码
2019/11/07 Javascript
使用Python实现下载网易云音乐的高清MV
2015/03/16 Python
windows下python安装pip图文教程
2018/05/25 Python
python自定义函数实现一个数的三次方计算方法
2019/01/20 Python
PyQt 实现使窗口中的元素跟随窗口大小的变化而变化
2019/06/18 Python
python实现的接收邮件功能示例【基于网易POP3服务器】
2019/09/11 Python
Python环境Pillow( PIL )图像处理工具使用解析
2019/09/12 Python
python 怎样将dataframe中的字符串日期转化为日期的方法
2019/09/26 Python
python之随机数函数的实现示例
2020/12/30 Python
公交公司毕业生求职信
2014/02/15 职场文书
银行自荐信怎么写
2015/03/05 职场文书
2016党员党课心得体会
2016/01/07 职场文书
pandas 操作 Excel操作总结
2021/03/31 Python
MySQL入门命令之函数-单行函数-流程控制函数
2021/04/05 MySQL
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA
win10频率超出范围怎么办?win10老显示超出工作频率范围的解决方法
2022/07/07 数码科技