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

闭包,有人说它是一种设计理念,有人说全部的函数都是闭包。到底什么是闭包?这个问题在面试是时候常常都会被问,不少小白一听就懵逼了,不知道如何回答好。
这个问题也有不少朋友在公众号给李老师留言了,问题表达方式不同,都是终归到一点,就是对闭包没有很清晰的理解。你们常常去网上找相关资料,可是对闭包的说法都是各类各样的,让你们对闭包的定义没有一个概念。
因此今天咱们来一块儿讲讲什么是闭包,帮助你们理解,今天的内容能够直接收藏起来。方便之后看。javascript

什么是闭包(Closure)

简单讲,闭包就是指有权访问另外一个函数做用域中的变量的函数。
MDN 上面这么说:闭包是一种特殊的对象。
它由两部分构成:函数,以及建立该函数的环境。环境由闭包建立时在做用域中的任何局部变量组成。前端

这种官方的概念是比较难理解的,在面试的时候说出来也不是很专业,由于没办法有个具体的逻辑。
我我的认为,理解闭包的关键在于:外部函数调用以后其变量对象本应该被销毁,但闭包的存在使咱们仍然能够访问外部函数的变量对象,这就是闭包的重要概念。
10692java

产生一个闭包

建立闭包最多见方式,就是在一个函数内部建立另外一个函数。下面例子中的 closure 就是一个闭包:
10698
闭包的做用域链包含着它本身的做用域,以及包含它的函数的做用域和全局做用域。面试

闭包的注意事项

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

闭包只能取得包含函数中任何变量的最后一个值
10758
你们看一下上面这个代码,arr数组中包含了10个匿名函数,每一个匿名函数都能访问外部函数的变量i,那么i是多少呢?
当arrFunc执行完毕后,其做用域被销毁,但它的变量对象仍保存在内存中,得以被匿名访问,这时i的值为10。
要想保存在循环过程当中每个i的值,须要在匿名函数外部再套用一个匿名函数,在这个匿名函数中定义另外一个变量而且当即执行来保存i的值。
10763
这时最内部的匿名函数访问的是num的值,因此数组中10个匿名函数的返回值就是1-10。安全

闭包中的this对象

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

内存泄漏

闭包会引用包含函数的整个变量对象,若是闭包的做用域链中保存着一个HTML元素,那么就意味着该元素没法被销毁。因此咱们有必要在对这个元素操做完以后主动销毁。
10791模块化

函数内部的定时器

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

闭包的应用

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

运用闭包的关键

闭包引用外部函数变量对象中的值;
在外部函数的外部调用闭包。
闭包的缺陷
闭包的缺点就是常驻内存会增大内存使用量,而且使用不当很容易形成内存泄露。
若是不是由于某些特殊任务而须要闭包,在没有必要的状况下,在其它函数中建立函数是不明智的,由于闭包对脚本性能具备负面影响,包括处理速度和内存消耗。
最后 来一道有关闭包的面试题
下面代码中,标记 ? 的地方输出分别是什么?
10829
你们结合今天讲解的内容,思考一下答案,你们能够把答案发到留意上吧。

好了,今天的讲解就那么多,若是你还有什么前端问题想提问的,或者你想李老师下次给你们讲什么内容,能够直接留意提问,说不定下次文章就会讲解了。若是你以为这篇文章对你有帮助,请转发点赞支持一下!

相关文章
相关标签/搜索