JavaScript中闭包之浅析解读(必看篇)


Posted in Javascript onAugust 25, 2016

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

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

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

以上这篇JavaScript中闭包之浅析解读(必看篇)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js实现一个省市区三级联动选择框代码分享
Mar 06 Javascript
jQuery对于显示和隐藏等常用状态的判断方法
Dec 13 Javascript
JS判断字符串字节数并截取长度的方法
Mar 05 Javascript
DOM中事件处理概览与原理的全面解析
Aug 16 Javascript
原生JS实现轮播效果+学前端的感受(防止走火入魔)
Aug 21 Javascript
使用Vue.js创建一个时间跟踪的单页应用
Nov 28 Javascript
bootstrap实现动态进度条效果
Mar 08 Javascript
JavaScript创建对象的七种方式(推荐)
Jun 26 Javascript
详解easyui基于 layui.laydate日期扩展组件
Jul 18 Javascript
浅谈Vue页面级缓存解决方案feb-alive(上)
Apr 14 Javascript
react native 仿微信聊天室实例代码
Sep 17 Javascript
微信小程序iOS下拉白屏晃动问题解决方案
Oct 12 Javascript
jquery点击切换背景色的简单实例
Aug 25 #Javascript
浅析Javascript ES6中的原生Promise
Aug 25 #Javascript
微信JS接口大全
Aug 25 #Javascript
JS解决iframe之间通信和自适应高度的问题
Aug 24 #Javascript
浅析Javascript ES6新增值比较函数Object.is
Aug 24 #Javascript
js图片上传前预览功能(兼容所有浏览器)
Aug 24 #Javascript
聊一聊jQuery插件uploadify使用方法
Aug 24 #Javascript
You might like
PHP与SQL注入攻击[一]
2007/04/17 PHP
IStream与TStream之间的相互转换
2008/08/01 PHP
php 多个submit提交表单 处理方法
2009/07/07 PHP
如何使用Linux的Crontab定时执行PHP脚本的方法
2011/12/19 PHP
PHP 年龄计算函数(精确到天)
2012/06/07 PHP
PHP+MySQL修改记录的方法
2015/01/21 PHP
CodeIgniter生成静态页的方法
2016/05/17 PHP
浅谈PHP中的错误处理和异常处理
2017/02/04 PHP
PHP+Apache环境中如何隐藏Apache版本
2017/11/24 PHP
Prototype 1.5.0_rc1 及 Prototype 1.5.0 Pre0小抄本
2006/09/22 Javascript
jQuery学习笔记[1] jQuery中的DOM操作
2010/12/03 Javascript
JavaScript+html5 canvas绘制缤纷多彩的三角形效果完整实例
2016/01/26 Javascript
jQuery+ajax的资源回收处理机制分析
2017/01/07 Javascript
Node.js五大应用性能技巧小结(必须收藏)
2017/08/09 Javascript
vue小图标favicon不显示的解决方案
2017/09/19 Javascript
Angular4学习教程之HTML属性绑定的方法
2018/01/04 Javascript
JS 实现百度搜索功能
2018/02/01 Javascript
vue本地打开build后生成的dist文件夹index.html问题
2019/09/04 Javascript
layer.alert自定义关闭回调事件的方法
2019/09/27 Javascript
天翼开放平台免费短信验证码接口使用实例
2013/12/18 Python
Python中IPYTHON入门实例
2015/05/11 Python
详解python里使用正则表达式的全匹配功能
2017/10/19 Python
python中学习K-Means和图片压缩
2017/11/20 Python
浅谈Django自定义模板标签template_tags的用处
2017/12/20 Python
python numpy 按行归一化的实例
2019/01/21 Python
Python3安装Pillow与PIL的方法
2019/04/03 Python
Python字典底层实现原理详解
2019/12/18 Python
Python-numpy实现灰度图像的分块和合并方式
2020/01/09 Python
Selenium基于PIL实现拼接滚动截图
2020/04/10 Python
python3检查字典传入函数键是否齐全的实例
2020/06/05 Python
Python爬虫之Selenium中frame/iframe表单嵌套页面
2020/12/04 Python
请说出几个常用的异常类
2013/01/08 面试题
教师自我鉴定
2013/12/13 职场文书
打架检讨书2000字
2014/02/22 职场文书
家长会欢迎词
2015/01/23 职场文书
Java生成日期时间存入Mysql数据库的实现方法
2022/03/03 Java/Android