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 相关文章推荐
extjs 3.31 TreeGrid实现静态页面加载json到TreeGrid里面
Apr 02 Javascript
js实现YouKu的漂亮搜索框效果
Aug 19 Javascript
Webpack 实现 AngularJS 的延迟加载
Mar 02 Javascript
jquery动态添加文本并获取值的方法
Oct 12 Javascript
Java  Spring 事务回滚详解
Oct 17 Javascript
jQuery UI仿淘宝搜索下拉列表功能
Jan 10 Javascript
基于jQuery实现简单人工智能聊天室
Feb 10 Javascript
小程序ios音频播放没声音问题的解决
Jul 11 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
Dec 03 Javascript
简单了解vue中父子组件如何相互传递值(基础向)
Jul 12 Javascript
原生js实现3D轮播图
Mar 21 Javascript
JavaScript实现轮播图特效
Apr 10 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
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
php绘制一条弧线的方法
2015/01/24 PHP
php防止CC攻击代码 php防止网页频繁刷新
2015/12/21 PHP
PHP实现批量清空删除指定文件夹所有内容的方法
2017/05/30 PHP
yii2 commands模式以及配置crontab定时任务的方法
2017/08/19 PHP
js中的如何定位固定层的位置
2014/06/15 Javascript
基于Jquery+div+css实现弹出登录窗口(代码超简单)
2015/10/27 Javascript
基于JavaScript实现 网页切出 网站title变化代码
2016/04/03 Javascript
JavaScript中的冒泡排序法
2016/08/03 Javascript
js 自带的sort() 方法全面了解
2016/08/16 Javascript
Angular中ng-bind和ng-model的区别实例详解
2017/04/10 Javascript
基于$.ajax()方法从服务器获取json数据的几种方式总结
2018/01/31 Javascript
一步步教会你微信小程序的登录鉴权
2018/04/09 Javascript
代码实例ajax实现点击加载更多数据图片
2018/10/12 Javascript
深入了解响应式React Native Echarts组件
2019/05/29 Javascript
Layui Form 自定义验证的实例代码
2019/09/14 Javascript
vue组件暴露和.js文件暴露接口操作
2020/08/11 Javascript
全面解读Python Web开发框架Django
2014/06/30 Python
Python中的元类编程入门指引
2015/04/15 Python
python3实现基于用户的协同过滤
2018/05/31 Python
Python设计模式之命令模式原理与用法实例分析
2019/01/11 Python
python网络编程:socketserver的基本使用方法实例分析
2020/04/09 Python
Funko官方商店:源自美国,畅销全球搪胶收藏玩偶
2018/09/15 全球购物
Molly Bracken法国电子商店:法国女性时尚品牌
2019/07/24 全球购物
linux面试题参考答案(6)
2016/06/23 面试题
给水排水工程专业毕业生推荐信
2013/10/28 职场文书
教师专业自荐书范文
2014/02/10 职场文书
大学生职业规划书的范本
2014/02/18 职场文书
资金主管岗位职责范本
2014/03/04 职场文书
绩效工资实施方案
2014/03/15 职场文书
超越自我演讲稿
2014/05/21 职场文书
文明上网主题班会
2015/08/14 职场文书
小学运动会开幕词
2016/03/04 职场文书
2019各种保证书范文
2019/06/24 职场文书
Nginx配置之实现多台服务器负载均衡
2021/08/02 Servers
Android移动应用开发指南之六种布局详解
2022/09/23 Java/Android