新手入门js闭包学习过程解析


Posted in Javascript onOctober 08, 2019

闭包,其实是一种语言特性,它是指的是程序设计语言中,允许将函数看作对象,然后能像在对象中的操作般在函数中定义实例(局部)变量,而这些变量能在函数中保存到函数的实例对象销毁为止,其它代码块能通过某种方式获取这些实例(局部)变量的值并进行应用扩展。

我们的理解:

其实闭包就是一个函数,一个外部函数通过调用函数并return返回出内部函数,这里的内部函数就是一个闭包;此时在内部函数中是可以访问到外部函数的变量的;

要想理解闭包,首先我们要了解栈堆内存和作用域链;首先我们来讲解栈堆内存:

首先我们来看个demo:

var a=1;
var obj={"name":"咸鱼"}

上面简单的两句代码,其实就是在内存中做了两件事,效果图如下:

新手入门js闭包学习过程解析

在js简单实现深浅拷贝(https://3water.com/article/171389.htm)一文中我们知道基本数据类型是存储在栈内存中的,引用数据类型是存储在堆内存中的,其实上面的两句代码在内存中就是做了两件事:1.首先在栈内存中开辟了一块空间用来存放a的变量和值;2.在堆内存中开辟了一块空间用来存储obj的值,同时在将地址指向栈内存中的变量名obj

如果我们在代码下面再加上一句obj={"name":'张三"},这个时候我们之前存储name为咸鱼的值也就是obj原来的值会被js中的垃圾回收机制回收掉,然后obj的值重新的指向{name:"张三"}这个值;

作用域链

再来看一下这个例子:

var a = 1;
function fn(){
  var b = 2;
  function fn1(){
    console.log(b);//2
    console.log(a);//1
  }
  fn1();
}
fn();

效果图如下:

新手入门js闭包学习过程解析

1.var a=1;这个时候我们是在全局执行环境的,浏览器的全局环境就是window作用域,我们的window作用域中有a和fn;

2.当我们往下走到fn的时候,栈内存会开辟一块新的执行环境,此时fn的执行环境中我们有b和fn1;

3.当我们接着往下走到fn1的时候,这时栈内存同样会开辟一块新的执行环境,此时fn1的执行环境中是没有任何变量数据的,但是我们在fn1中输出a、b,我们都是可以读取到的;这是因为程序在读取变量的时候是从内到外的开始读的,是随着fn1开始往上一层一层的查找,是这样的执行顺序(fn1 = > fn = > window),如果找到window中还没有读取到变量,这时程序才会报错;

当然在执行的过程中,垃圾回收机制如果检测到程序执行完了是会进行垃圾回收的,避免造成内存泄露等问题;就是说我们的fn1里面执行完之后fn1的作用域就会被销毁,接着程序执行fn,fn执行完之后fn就会被销毁;往上执行到全局的时候,整个程序就没有了fn的作用域和fn1的作用域,只剩下浏览器的全局作用域window,这个时候window里只剩a和fn;

了解了上面的作用域链和栈内存和堆内存的知识之后,我们来开始讲解js闭包:

function outer() {
   var a = '123'
  
  return function add(){

//在这里因为作用域的关系,add是能访问到outer的所有变量的,但是outer是访问不到add的变量;


//所以思路一转,把add的值作为结果return出来变通实现outer外部函数访问到了内部函数变量

  // add就是一个闭包函数,因为他能够访问到outer函数的作用域,add中没有找到变量a,则会继续往上层作用域找
    console.log(a);
  }
}
var inner = outer()  // 获得add闭包函数
inner()  //"123"

首先我们可以看到,在全局作用域下我们是有一个outer函数的,outer作用域里面有a和add,add作用域里面执行控制台输出a的变量,此时这里的add函数就形成了一个闭包,因为add函数里面需要访问到outer作用域下的a变量,而他们不处在同一个作用域中,所以两者相互牵引,需要输出a,上面outer中的变量a就必须得在,作用域链查找到outer的时候找到a了,输出a的时候,垃圾回收机制会认为add还没有执行完成,因为此时的作用域链查找已经到了outer作用域下,所以不会清理a的内存空间;所以这就会带来一个问题:如果我们多次的使用闭包,则会给我们的程序带来内存占用过多,导致性能问题;

函数内部能访问全局变量是javascript语言的特殊之处,但是如果我们想达到函数外部能访问内部变量的时候,我们就可以使用闭包,这就是闭包给我们带来的便利;

闭包的优缺点:

优点:

1.可以读取函数内部的变量

2.可以避免全局污染

缺点:

1.闭包会导致变量不会被垃圾回收机制所清除,会大量消耗内存;

2.不恰当的使用闭包可能会造成内存泄漏的问题;

总结:

1.作用域链查找变量的方式是一层一层的往上查找,直到找到为止,如果找到window全局作用域还未找到,就报undefined;

2.嵌套函数中,因为不在同一作用域,正常情况下内外部函数是访问不到内部函数的,但是通过闭包可以实现;

3.尽可能少的使用闭包,因为会造成内存消耗大以及有可能造成内存泄露(如果不需要的时候,不要随便使用);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery 初体验(建议学习jquery)
Apr 25 Javascript
js修改input的type属性及浏览器兼容问题探讨与解决
Jan 23 Javascript
Node.js中使用Log.io在浏览器中实时监控日志(等同tail -f命令)
Sep 17 Javascript
node.js操作mongoDB数据库示例分享
Nov 26 Javascript
EasyUI加载完Html内容样式渲染完成后显示
Jul 25 Javascript
轻松实现js选项卡切换效果
Sep 24 Javascript
Angular中使用$watch监听object属性值的变化(详解)
Apr 24 Javascript
浅谈node中的cluster集群
Jun 02 Javascript
JS动态图片的实现方法完整示例
Jan 13 Javascript
浅谈vue获得后台数据无法显示到table上面的坑
Aug 13 Javascript
JavaScript实现网页动态生成表格
Nov 25 Javascript
JavaScript前端面试扁平数据转tree与tree数据扁平化
Jun 14 Javascript
关于JSON解析的实现过程解析
Oct 08 #Javascript
解决webpack多页面内存溢出的方法示例
Oct 08 #Javascript
javascript简单实现深浅拷贝过程详解
Oct 08 #Javascript
webpack HappyPack实战详解
Oct 08 #Javascript
简单了解vue中的v-if和v-show的区别
Oct 08 #Javascript
在Koa.js中实现文件上传的接口功能
Oct 08 #Javascript
vue-cli和v-charts实现可视化图表过程解析
Oct 08 #Javascript
You might like
探讨PHP中this,self,parent的区别详解
2013/06/08 PHP
php模拟post提交数据的方法
2015/02/12 PHP
[原创]smarty简单模板变量输出方法
2016/07/09 PHP
Apache+PHP+MySQL搭建PHP开发环境图文教程
2020/08/06 PHP
javascript function、指针及内置对象
2009/02/19 Javascript
jQuery初学:find()方法及children方法的区别分析
2011/01/31 Javascript
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
Dom 学习总结以及实例的使用介绍
2013/04/24 Javascript
通过一段代码简单说js中的this的使用
2013/07/23 Javascript
判断文件是否正在被使用的JS代码
2013/12/21 Javascript
BAT及各大互联网公司2014前端笔试面试题--JavaScript篇
2014/10/29 Javascript
AspNet中使用JQuery上传插件Uploadify详解
2015/05/20 Javascript
JavaScript代码判断点击第几个按钮
2015/12/13 Javascript
5个最顶级jQuery图表类库插件【jquery插件库】
2016/05/05 Javascript
Node.js 中exports 和 module.exports 的区别
2017/03/14 Javascript
js中获取键盘按下键值event.keyCode、event.charCode和event.which的兼容性详解
2017/03/15 Javascript
webpack之引入图片的实现及问题
2018/10/08 Javascript
用Object.prototype.toString.call(obj)检测对象类型原因分析
2018/10/11 Javascript
详解Angular Forms中自定义ngModel绑定值的方式
2018/12/10 Javascript
vue中使用mxgraph的方法实例代码详解
2019/05/17 Javascript
Python 专题二 条件语句和循环语句的基础知识
2017/03/19 Python
redis之django-redis的简单缓存使用
2018/06/07 Python
python实现猜数字小游戏
2020/03/24 Python
Selenium控制浏览器常见操作示例
2018/08/13 Python
详解一种用django_cache实现分布式锁的方式
2019/09/01 Python
Python 获取命令行参数内容及参数个数的实例
2019/12/20 Python
ALLSAINTS英国官网:伦敦新锐潮流品牌
2016/09/19 全球购物
英国领先的餐饮折扣俱乐部:Gourmet Society
2020/07/26 全球购物
介绍一下HDLC(High-Level Data Link Control)高层数据链路协议
2012/01/21 面试题
政法大学毕业生自荐信范文
2014/01/01 职场文书
文体活动实施方案
2014/03/27 职场文书
分公司经理任命书
2014/06/05 职场文书
解除劳动关系协议书2篇
2014/11/28 职场文书
2014教师专业技术工作总结
2014/12/03 职场文书
岗位职责范本大全
2015/02/26 职场文书
前端JavaScript大管家 package.json
2021/11/02 Javascript