面试前端,当面试官问你,谈谈你对闭包的理解的时候,该怎么回答

经常被问到这个问题,现在的情况是是给我一个东西我知道是闭包,但是让我说什么是闭包,我却说不太好,面试官这么问的时候,我该怎么回答,会显得比较有亮点一些。谢谢~

阅读 24.1k
6 个回答

作为面试官,楼上的大部分答案我都不愿意听到,比如:

  1. 可以阻止变量被 GC 回收(这里我经常会插一个问题:能不能介绍一下 GC 的执行机制?)
  2. 可以实现某个特性,比如私有变量等

这些都是闭包的结果,或者闭包的用法,不是闭包本身。这些用法和现象是可以通过闭包的机制推出来的。另外,闭包在 JS 里非常重要,我认为还是有必要了解清楚的。

JS 的闭包包含以下要点:

  1. 函数声明的时候,会生成一个独立的作用域
  2. 同一作用域的对象可以互相访问
  3. 作用域呈层级包含状态,形成作用域链,子作用域的对象可以访问父作用域的对象,反之不能;另外子作用域会使用最近的父作用域的对象

其实第二点才是真闭包,不过我们通常把“闭包”的概念扩大到上面3点之和。基于此3点,其它无论用法还是问题都可以推出来。


另外,关于垃圾回收的问题,《JS 高级程序设计》里面有比较清晰的介绍,并不是闭包会导致内存泄漏,就像我们不能说菜刀会杀人一样。所以建议大家把 GC 也搞清楚,为什么闭包有时候可能导致内存泄漏,怎么处理?哪些浏览器会发生哪些不会发生,这样自己写起代码来也更容易操作。毕竟,所有的 JS 都包含闭包。

简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。

用for再举个例子

//循环里面包含闭包函数
function box(){
    var arr = [];
    for(var i=0;i<5;i++){
        arr[i] = function(){
            return i;//由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5
        }//这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i,
    }//当找到这个i的时候,for循环已经循环完毕了,所以最终会返回5
    return arr;
}

闭包后

function box(){
    var arr = [];
    for(var i=0;i<5;i++){
        arr[i] = (function(num){                    //自我执行,并传参(将匿名函数形成一个表达式)(传递一个参数)
            return num;                            //这里的num写什么都可以                    
        })(i);                                    //这时候这个括号里面的i和上面arr[i]的值是一样的都是取自for循环里面的i                            
    }                                            
    return arr;
}

我在问这个问题的时候,我其实并不想听到对方说

闭包就是能够访问到其他函数作用域

闭包就是能够将变量保存在内存当中

之类这样的话的。

因为别人从网上硬记下来也能这么说,而且这些也都只是闭包的现象。我更希望对方能跟从JS的执行开始讲、一个函数执行前后的内存回收过程,再阐述闭包形成的原因,这样又会导致什么问题,应该怎么解决。最后再讲有什么用途,或者说自己曾经有什么需求需要闭包来实现。

这么一轮讲下来,我觉得这位同学至少对闭包是有研究了,而不是死记硬背了一些面试题之类的。

闭包用来让外部作用域的非全局变量不随着外部函数的结束被销毁的同时又不污染全局环境。
这里提供一种思路,借助闭包来实现单例模式。

var C = function () {};
var proxyC = (function () {
    var instance;
    return function () {
        if (!instance) {
            instance = new C;
        };
        return instance;
    }
})();
var b = new proxyC();
var c = new proxyC();
console.log(b === c) //true

一个可以从内部调用外部函数的变量就是闭包。主要讲一下他的缺点会导致内存泄露,然后要指定Null解决内存泄露,作用是模仿块级作用域。这里主要是针对面试:回答要点是“作用,副作用,解决副作用 和 实用的场景”这几个地方回答了就好了

闭包是函数
作为内部函数保存着对外部函数中变量的引用

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题