面试遇见的闭包

1、什么是闭包?

闭包就是指有权访问另一个函数作用域中变量的函数,通俗点讲闭包就是能够读取其他函数变量的函数。常见的构造方法,是在一个函数内部定义另外一个函数。内部函数可以引用外层的参数和变量;参数和变量不会被垃圾回收机制回收。除非用立即执行函数来解决。所以闭包的特性:

(1)函数内再嵌套函数;

(2)内部函数可以引用外层的参数和变量;

(3)参数和变量不会被垃圾回收机制回收。

图片 1

 1         function fn1() {
 2             var a = 1 ;
 3             function fn2() {
 4                 alert(a);
 5             }
 6             return fn2;
 7         }
 8 
 9         var result = fn1();
10         result();  //1

图片 2

上述函数fn2就是一个闭包,我们可以通过返回fn2获取到fn1中的变量。

其实在理解闭包前理解JavaScript的作用域是有必要的。

2、闭包的用途

(1)通过闭包去访问函数内部的变量;

(2)使某些变量常驻内存。

图片 3

 1         //没有闭包情况下变量a的情况
 2         function add() {
 3             var a = 1;
 4             a++;
 5             alert(a);
 6         }
 7         add();   //2
 8         add();   //2
 9 
10         //有闭包的方式下
11         function add2() {
12             var a = 1;
13             function fn() {
14                 a++;
15                 alert(a);
16             }
17             return fn;
18         }
19         var result = add2();
20         result();  //2
21         result();  //3

图片 4

在有闭包的情况下,result()的两次输出分别是2、3,这说明aad2中的a变量一直在内存当中,并没有因为add2的调用后被垃圾回收机制回收(garbage collection)。

为什么会产生这样的情况?这是因为add2是fn的父亲函数,而在全局环境当中,fn其实是被赋给了全局变量result的,而result只会在全局环境执行完所有代码之后才会被回收,所以就导致了fn常驻内存,而fn的存在又依赖于父亲函数add2,所以add2在被调用之后也不会被GC(垃圾回收机制)回收,也始终存在于内存当中。

下面讲一下我在面试中遇到的小问题

3、闭包可能会引发的问题

由于IE9之前的版本对JSript对象和COM对象使用了不同的垃圾回收机制,所以闭包在IE9之前的版本中会导致内存泄漏问题。具体来说就是,如果闭包中保存着一个HTML元素,那么这个元素将无法被销毁,直到退出程序或关闭浏览器。

图片 5

1     <script>
2         window.onload = function () {
3             var oBox = document.getElementById('box');
4 
5             oBox.onclick = function () {
6                 alert(oBox.id);
7             }
8         };
9     </script>

图片 6

像上述的情况下就发生了内存泄漏,因为在闭包中创建了一个循环引用。可以通过以下方法得到解决:

图片 7

 1     <script>
 2         window.onload = function () {
 3             var oBox = document.getElementById('box');
 4 
 5             oBox.onclick = function () {
 6                 alert(oBox.id);
 7             };
 8 
 9             //方法一
10             window.onunload = function () {
11                 oBox.onclick = null;
12             }
13         };
14 
15         //方法二
16         window.onload = function () {
17             var oBox = document.getElementById('box');
18             var id = oBox.id;
19 
20             oBox.onclick = function () {
21                 alert(id);
22             };
23 
24             oBox = null;
25         };
26         
27     </script>

图片 8

 

图片 9

图片1发自简书App

当时我看到这个问题,不经过大脑思考直接输出的是My Object 然而正确的答案是The Window。

后来我理解了,object.getNameFunc(),就相当于是 function(){ retuen this.name }()全局的匿名函数 全局的匿名函数this指向的是window 所以答案是The Window。

图片 10

图片2发自简书App

图二和图一很相似,显然当时的我又做错了,正确的答案是My Object。

本文由金沙官网线上发布于Web前端,转载请注明出处:面试遇见的闭包

您可能还会对下面的文章感兴趣: