闭包,有人说它是一种设计理念,有人说所有的函数都是闭包。到底什么是闭包?这个问题在面试是时候经常都会被问,很多小白一听就懵逼了,不知道如何回答好。

这个问题也有很多朋友在公众号给李老师留言了,问题表达方式不一样,都是终归到一点,就是对闭包没有很清晰的理解。大家经常去网上找相关资料,但是对闭包的说法都是各种各样的,让大家对闭包的定义没有一个概念。
更多网页前端开发教程,行业资讯,面试技巧,欢迎关注前端开发学习公众号:网页前端开发学习

今天我们就来一起讲讲什么是闭包,帮助大家理解,今天的内容可以直接收藏起来。方便以后看。

什么是闭包(Closure)

简单讲,闭包就是指有权访问另一个函数作用域中的变量的函数。
MDN 上面这么说:闭包是一种特殊的对象。
它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。
这种官方的概念是比较难理解的,在面试的时候说出来也不是很专业,因为没办法有个具体的逻辑。
我个人认为,理解闭包的关键在于:外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象,这就是闭包的重要概念。

产生一个闭包

创建闭包最常见方式,就是在一个函数内部创建另一个函数。下面例子中的 closure 就是一个闭包:
闭包的作用域链包含着它自己的作用域,以及包含它的函数的作用域和全局作用域。

闭包的注意事项

.通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。
从上述代码可以看到add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的环境。在 add5 的环境中,x 为 5。而在 add10 中,x 则为 10。最后通过 null 释放了 add5 和 add10 对闭包的引用。
在javascript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收机制回收;
如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。

闭包只能取得包含函数中任何变量的最后一个值

大家看一下上面这个代码,arr数组中包含了10个匿名函数,每个匿名函数都能访问外部函数的变量i,那么i是多少呢?
当arrFunc执行完毕后,其作用域被销毁,但它的变量对象仍保存在内存中,得以被匿名访问,这时i的值为10。
要想保存在循环过程中每一个i的值,需要在匿名函数外部再套用一个匿名函数,在这个匿名函数中定义另一个变量并且立即执行来保存i的值。
这时最内部的匿名函数访问的是num的值,所以数组中10个匿名函数的返回值就是1-10。

闭包中的this对象

在上面这段代码中,obj.getName()()实际上是在全局作用域中调用了匿名函数,this指向了window。
这里要理解函数名与函数功能是分割开的,不要认为函数在哪里,其内部的this就指向哪里。
window才是匿名函数功能执行的环境。
如果想使this指向外部函数的执行环境,可以这样改写:
在闭包中,arguments与this也有相同的问题。下面的情况也要注意:
obj.getName();这时getName()是在对象obj的环境中执行的,所以this指向obj。
(obj.getName = obj.getName)赋值语句返回的是等号右边的值,在全局作用域中返回,所以(obj.getName = obj.getName)();的this指向全局。要把函数名和函数功能分割开来。

内存泄漏

闭包会引用包含函数的整个变量对象,如果闭包的作用域链中保存着一个HTML元素,那么就意味着该元素无法被销毁。所以我们有必要在对这个元素操作完之后主动销毁。

函数内部的定时器

当函数内部的定时器引用了外部函数的变量对象时,该变量对象不会被销毁。

闭包的应用

应用闭包的主要场合是:设计私有的方法和变量。
任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。私有变量包括函数的参数、局部变量和函数内定义的其他函数。
把有权访问私有变量的公有方法称为特权方法(privileged method)。
在这里,我们需要理解两个概念:
模块模式(The Module Pattern):为单例创建私有变量和方法。
单例(singleton):指的是只有一个实例的对象。JavaScript 一般以对象字面量的方式来创建一个单例对象。
上面是普通模式创建的单例,下面使用模块模式创建单例:
匿名函数最大的用途是创建闭包,并且还可以构建命名空间,以减少全局变量的使用。从而使用闭包模块化代码,减少全局变量的污染。
在这段代码中函数 addEvent 和 removeEvent 都是局部变量,但我们可以通过全局变量 objEvent 使用它,这就大大减少了全局变量的使用,增强了网页的安全性。

运用闭包的关键

  • 闭包引用外部函数变量对象中的值;
  • 在外部函数的外部调用闭包。

闭包的缺陷

  • 闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露。
  • 如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。

最后 来一道有关闭包的面试题

下面代码中,标记 ? 的地方输出分别是什么?
大家结合今天讲解的内容,思考一下答案,大家可以把答案发到留意上吧。
好了,今天的讲解就那么多,如果你还有什么前端问题想提问的,或者你想李老师下次给大家讲什么内容,可以直接关注前端学习公众号:【网页前端开发学习】留意提问,说不定下次文章就会讲解了。
如果你觉得这篇文章对你有帮助,请转发点赞支持一下!

面试官问我:什么是JavaScript闭包,我该如何回答相关推荐

  1. 面试官问你期待工资多少时,该怎么回答?

    面试时,面试官问我期望工资是多少,我想都没想就要了6000元月薪,然后顺利入职了,可直到2年后,老板给我加薪时,我才知道当初面试的工资要少了,老板教会了我,如果面试官问期望工资是多少,该如何回答,但是 ...

  2. 面试官问你的缺点是什么,该如何回答?

    作为一个资深HR,此题感触颇深. 当我微笑着问你,可以谈谈自己的缺点吗?如果应聘者低头莞尔一笑,或羞涩或含蓄地说: "我妈妈说,我最大的缺点,就是太执着,不撞南墙不回头--" &q ...

  3. 面试官问你为什么离开上一家公司该怎么回答?(二)

    大部分人都不太懂为什么HR会问这个问题. 也会有很多人问背调怎么办. 所以先来跟大家一起看一看,HR在问到这个问题的时候,倒底是关心什么? 会有人说,你又不是HR,你怎么知道HR心里想什么?你猜我为什 ...

  4. c gui qt 4编程第二版_面试官问Linux下如何编译C程序,如何回答?为你编译演示

    文章来源:嵌入式大杂烩 作者:ZhengNL Windows下常用IDE来编译,Linux下直接使用gcc来编译,编译过程是Linux嵌入式编程的基础,也是嵌入式高频基础面试问题. 一.命令行编译及各 ...

  5. java反射 虚拟机优化_面试官问我:Java反射是什么?我回答竟然不上来......

    每天凌晨00点00分,第一时间与你相约 每日英文 We all have moments of desperation. But if we can face them head on, that's ...

  6. 面试官问:对我们公司,你还有想了解的吗?99%的面试人都不懂这样面试

    有一句话说:面试就像谈恋爱,只有彼此对上眼,情感产生共鸣时,方可成交! 今天就来和大家聊一聊面试中我们回答完面试官的问题后,突然来一句:你对我们公司还有什么想了解的吗?大部分面试者是不是经常被面试官提 ...

  7. obj: object是什么意思_面试官问你JavaScript基本类型时他想知道什么?

    本文原载于SegmentFault专栏"前端小将" 整理编辑:SegmentFault 面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括: 1.基本类型(值类 ...

  8. 面试官问:能否模拟实现JS的bind方法(高频考点)

    可以点击上方的话题JS基础系列,查看往期文章 写于2018年11月21日,发布在掘金阅读量1.3w+ 前言 这是面试官问系列的第二篇,旨在帮助读者提升JS基础知识,包含new.call.apply.t ...

  9. 面试官问:JS的this指向

    写于2018年12月25日,发布在掘金上阅读量近一万,现在发布到微信公众号申明原创. 前言 这是面试官问系列的第四篇,旨在帮助读者提升JS基础知识,包含new.call.apply.this.继承相关 ...

  10. 后处理程序文件大小的变量_【每日一题】(17题)面试官问:JS中事件流,事件处理程序,事件对象的理解?...

    关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 2020,实「鼠」不易 2021,「牛」转乾坤 风劲潮涌当扬帆,任重道远须奋蹄! 一.前言 2020.12.23 立 ...

最新文章

  1. 手把手教你Tableau高级数据分析功能(附数据集)
  2. 转载:每一个程序员要遵守的一些优秀编程风格
  3. 分布式架构的分布式文件系统
  4. 免安装Mysql在Mac中的神坑之Access denied for user 'root'@'localhost' (using password: YES)
  5. 牛客网选择题之linux
  6. 想要换壁纸,看这个网站就够了!
  7. windows server 2003 32位支持8G内存
  8. 关闭SqlConnection的方法
  9. Java连接数据库导致连接数占满
  10. Apache2 Linux 的安装与介绍
  11. perf top 实时分析 CPU 使用情况
  12. 骨传导也有动铁单元般的音质,绝对品质,真的是诚意满满
  13. NGINX工作原理解析
  14. html css print打印,打印样式
  15. MIMO信道的信道容量
  16. 【Axure交互教程】 隐藏页面滚动条的3种方法
  17. oracle集群服务创建表空间,Oracle数据库集群添加表空间操作规范
  18. c 工厂模式与mysql链接_工厂模式连接数据库
  19. 51单片机指令快速记忆方法总结
  20. 修改host文件原理 localhost,127.0.0.1之间有什么区别

热门文章

  1. python两个元组相加_《第5章 Python 列表与元组》5.1.3 序列相加(Adding)!
  2. 二维数组:随机生产,遍历,判断两个数组一维二维长度,和内容是否一致
  3. java 防止表单重复提交
  4. java中select的用法_mybaties中select用法,以及常用增删改查
  5. leetcode614. 二级关注者(SQL)
  6. leetcode142 环形链表II
  7. leetcode72 编辑距离
  8. redis——发布和订阅
  9. 《Python Cookbook 3rd》笔记(1.10):删除序列相同元素并保持顺序
  10. C++ Byte转十六进制字符串输出