文章目录

  • 前言
  • 一、闭包概念
  • 二、闭包的副作用
  • 三、闭包的用途
    • 1.在函数外部读取函数的内部变量
    • 2.利用外部函数变量缓存值
  • 四、总结

前言

写本《JavaScript简餐》系列文章的目的是记录在阅读学习《JavaScript高级程序设计(第4版)》一书时出现的各个知识点。虽是对读书的笔记和总结,但是希望它轻量、简洁、犀利,不会引起阅读疲劳,可以在碎片化时间和闲暇之余轻巧地沐浴一下知识点。每篇文章只针对一个小部分进行讲解式的梳理,来达到个人复习总结和分享知识的目的。


一、闭包概念

闭包:指的是那些引用了另一个函数作用域中变量的函数。通常是在嵌套函数中实现的。例如:

function Person() {let age = 29;return function sayAge() {console.log(age);};
}

在这里,内部函数sayAge函数引用了外部函数Perosn的变量age,即应用了另一个函数作用域中的变量。所以,sayAge函数就是一个闭包。


二、闭包的副作用

一般函数在执行完毕后,局部活动对象会被销毁,内存中就只剩下全局作用域。(在这里要说明一下,函数执行上下文中会有一个包含其中变量的对象,这个对象中包含函数的arguments、函数局部变量以及函数中定义的对象,我们称这个对象为变量对象。而在函数执行时,这个变量对象就称为活动对象。)但是当你定义一个闭包后,由于闭包会保留外部函数的作用域,导致外部函数的活动对象不能在它执行完毕后销毁,此时闭包的作用域链中仍然有对外部函数活动对象的引用。来看一个例子:

function Person() {let age = 29;addAge = function () { // addAge没有用var、let或者const声明,所以相当于定义在全局的函数++age;};return function sayAge() {console.log(age);};
}let result = Person();result(); // 29
addAge();
result(); // 30

在这里,我们先运行result()(要知道我们的这个result函数等于sayAge函数),得到了age的值29,之后我们借助addAge()将age的值加1,再次运行result()时我们发现age的值变成30了。这足以证明,Person函数的局部变量age一直存在于内存中,并没有在调用后被销毁。这就会导致垃圾回收程序无法回收这个变量,从而引发内存泄漏。
对此,我们可以通过调用result()后将其设置为null来解除对外部函数的引用来释放内存,如下:

function Person() {let age = 29;addAge = function () { // addAge没有用var、let或者const声明,所以相当于定义在全局的函数++age;};return function sayAge() {console.log(age);};
}let result = Person();result(); // 29result = null; // 解除对函数的引用,这样就可以释放内存

闭包会保留包含它们的函数的作用域,所以比其他函数更占用内存。过度使用闭包可能导致内存过度占用,因此建议仅在十分必要时使用。


三、闭包的用途

1.在函数外部读取函数的内部变量

众所周知,在函数外部时不可以调用函数内部定义的变量的。但是通过闭包我们可以访问到函数的内部变量。具体原理是在函数中将闭包作为返回值返回,之后在函数外部再次调用这个闭包即可。例如:

function Person() {let age = 29;return function sayAge() {console.log(age);};
}let result = Person(); // 29
//当然也可以这样调用:
Person()();

2.利用外部函数变量缓存值

以防抖函数为例:

function debounce(fn, wait = 1000) {let timer;return function () {if (timer) {clearTimeout(timer);}timer = setTimeout(() => {fn.apply(this, arguments);}, wait);};
}

这里利用闭包,让外部函数定义的timer一直存在于内存中不被销毁,当防抖函数再次执行时就可以直接从内存中读取timer来判断是否还存在,从而来进行防抖限制。


四、总结

以上就是今天要讲的内容,今天介绍了一下闭包的概念、闭包的副作用以及它的作用。下一篇,我们来讲一下ES6新增的尾调用优化。撒花~

JavaScript简餐——闭包相关推荐

  1. JavaScript简餐——函数尾调用优化

    文章目录 前言 一.认识尾调用优化 二.尾调用优化的条件 三.尾调用优化实例 总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅读学习<JavaScript高级程序 ...

  2. JavaScript简餐——那些函数属性与方法(call、apply和bind)

    文章目录 前言 一.arguments对象的callee属性 二.函数的caller属性 三.new.target 四.call.apply和bind方法 1.call方法 2.apply方法 3.b ...

  3. JavaScript简餐——关于盗用构造函数

    文章目录 前言 一.什么是盗用构造函数? 二.使用实例 三.参数传递 四.盗用构造函数的问题所在 五.总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅读学习<Ja ...

  4. JavaScript简餐——初见Promise

    文章目录 前言 一.Promise基础 1.Promise状态机 2.通过执行函数 控制Promise的状态 3.Promise.resolve() 4.Promise.reject() 5.同步/异 ...

  5. JavaScript简餐——初识函数

    文章目录 前言 初始函数 1.函数声明 2.函数表达式 3.箭头函数(ES6新特性) 4.使用Function构造函数 总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅 ...

  6. JavaScript简餐——类构造函数

    文章目录 前言 一.类的构造函数及其实例化 二.把类当成特殊函数 三.总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅读学习<JavaScript高级程序设计(第 ...

  7. JavaScript简餐——寄生组合继承

    文章目录 前言 一.什么是寄生组合继承? 二.寄生组合继承的基本模式 三.总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅读学习<JavaScript高级程序设计 ...

  8. JavaScript简餐——原型式继承

    文章目录 前言 一.什么是原型式继承? 二.ECMAScript5中的原型式继承 三.总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅读学习<JavaScript ...

  9. JavaScript简餐——细看函数的参数

    文章目录 前言 一.理解参数 二.箭头函数中的参数 三.总结 前言 写本<JavaScript简餐>系列文章的目的是记录在阅读学习<JavaScript高级程序设计(第4版)> ...

最新文章

  1. oracle 条件动态视图,oracle最重要的9个动态性能视图
  2. 输入n个字符串字典序排序_FSST - 快速字符串压缩算法
  3. android listview显示数据库内容
  4. effective C++ 条款 47:使用traits classes表现类型信息
  5. 【行业报告】中国金融科技2017专题研究报告——易观智库
  6. Effective Java之通过私有构造器强化不可实例化能力(四)
  7. 【CodeForces - 155C】Hometask (字符串,思维,贪心,熟悉句式)(总结)
  8. php react-native,React-Native+Mobx实现商城APP
  9. 定时器加状态转移图方式实现DS18B20
  10. matlab中二阶偏导数,matlab中二元函数的一阶和二阶偏导数
  11. 【VUE】vue程序设计----模仿网易严选
  12. Git Extension 合并分支
  13. 高价值的聚合支付源码修复版+带后台/语音播报
  14. 使用DISM修复系统
  15. 修真院java_【修真院JAVA小課堂】JMeter的簡單介紹
  16. openeuler 21.3 : 使用LVM管理硬盘
  17. 抖音直播用什么手机效果最好 抖音直播手机哪款好2023
  18. 2019年2月18日,异常作业
  19. 在Mybaties中进行数据查询时,表中字段名和属相名没有对应起来,查询的结果总null,一下是解决方法
  20. 【分享】在小米实习到SP+转正

热门文章

  1. 小学计算机老师每周周记,【推荐】小学周记五篇
  2. 计算机系统中声卡的作用,声卡是什么,告诉你声卡的作用!
  3. 我是怎样向别人提问题的?
  4. asList使用注意事项
  5. numpy.array 的shape属性理解
  6. 这几种人,是公司裁员的主要对象。
  7. 《Java8学习笔记》读书笔记(7)
  8. 使用虚拟机和主机进行共享文件
  9. 英灵神殿云服务器配置要求,英灵神殿云服务器MOD安装教程[多图]
  10. lol峡谷之巅区服务器位置,LOL峡谷之巅地址