新手入门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 相关文章推荐
javascript结合html5 canvas实现(可调画笔颜色/粗细/橡皮)的涂鸦板
Apr 27 Javascript
解决JS中乘法的浮点错误的方法
Jan 03 Javascript
jQuery使用attr()方法同时设置多个属性值用法实例
Mar 26 Javascript
javascript实现删除前弹出确认框
Jun 04 Javascript
原生javascript实现匀速运动动画效果
Feb 26 Javascript
jQuery UI结合Ajax创建可定制的Web界面
Jun 22 Javascript
浅谈Angular2 模块懒加载的方法
Oct 04 Javascript
微信公众号生成新浪短网址的实现(快速生成)
Aug 18 Javascript
uni-app自定义导航栏按钮|uniapp仿微信顶部导航条功能
Nov 12 Javascript
JS继承定义与使用方法简单示例
Feb 19 Javascript
django简单的前后端分离的数据传输实例 axios
May 18 Javascript
解决vue加scoped后就无法修改vant的UI组件的样式问题
Sep 07 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
自制短波长线天线频率预选器 - 成功消除B2K之流的镜像
2021/03/02 无线电
PHP正则删除HTML代码中宽高样式的方法
2017/06/12 PHP
Thinkphp5+uploadify实现的文件上传功能示例
2018/05/26 PHP
php模拟post提交请求调用接口示例解析
2020/08/07 PHP
JS 控制非法字符的输入代码
2009/12/04 Javascript
js 高效去除数组重复元素示例代码
2013/12/19 Javascript
JavaScript按位运算符的应用简析
2014/02/04 Javascript
JavaScript获取某年某月的最后一天附截图
2014/06/23 Javascript
JS判断变量是否为空判断是否null
2014/07/25 Javascript
innerHTML在IE中报错解决方案
2014/12/15 Javascript
JavaScript中的对象序列化介绍
2014/12/30 Javascript
JS与HTML结合使用marquee标签实现无缝滚动效果代码
2016/07/05 Javascript
Bootstrap基本组件学习笔记之分页(12)
2016/12/08 Javascript
vue ssr 指南详读
2018/06/29 Javascript
vue多次循环操作示例
2019/02/08 Javascript
Vue 组件修改根实例的数据的方法
2019/04/02 Javascript
浅析vue插槽和作用域插槽的理解
2019/04/22 Javascript
[00:42]《辉夜杯》—职业组预选赛12月3日15点 正式打响
2015/12/03 DOTA
[56:24]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#1Liquid VS MVP.Phx第二局
2016/03/04 DOTA
[03:02]安得倚天剑,跨海斩长鲸——中国军团出征DOTA2国际邀请赛
2018/08/14 DOTA
django+xadmin+djcelery实现后台管理定时任务
2018/08/14 Python
Python常见读写文件操作实例总结【文本、json、csv、pdf等】
2019/04/15 Python
解决win7操作系统Python3.7.1安装后启动提示缺少.dll文件问题
2019/07/15 Python
使用TensorFlow-Slim进行图像分类的实现
2019/12/31 Python
flask利用flask-wtf验证上传的文件的方法
2020/01/17 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
2020/03/20 Python
keras 自定义loss model.add_loss的使用详解
2020/06/22 Python
黄色火烈鸟:De Gele Flamingo
2019/03/18 全球购物
旺仔牛奶广告词
2014/03/20 职场文书
yy司仪主持词
2014/03/22 职场文书
公司感恩节活动策划书
2014/10/11 职场文书
硕士学位申请报告
2015/05/15 职场文书
步步惊心观后感
2015/06/12 职场文书
机关单位2016年创先争优活动总结
2016/04/05 职场文书
解决python绘图使用subplots出现标题重叠的问题
2021/04/30 Python
Spring Cloud Gateway去掉url前缀
2021/07/15 Java/Android