• 技术文章 >后端开发 >php教程

    javascript - 面试题:为什么要用闭包?

    2016-12-01 00:26:03原创979

    看了这个回答似乎也不是了解的很透彻啊

    我是学Java的。今天在面试的时候面试官提及匿名类,我说Java8里面提供了Lamada式,在JS里也有闭包这个概念。面试官问什么是闭包?为什么要用闭包?

    面试官似乎不是很满意这样的回答。不知各位大神对这个问题有什么看法?

    回复内容:

    看了这个回答似乎也不是了解的很透彻啊

    我是学Java的。今天在面试的时候面试官提及匿名类,我说Java8里面提供了Lamada式,在JS里也有闭包这个概念。面试官问什么是闭包?为什么要用闭包?

    面试官似乎不是很满意这样的回答。不知各位大神对这个问题有什么看法?

    闭包,顾名思义,就是把馒头变成包子~

    馒头全是面粉,包上馅就成了包子

    包子是带馅的馒头

    闭包是自带运行环境的函数

    发哥是自带背景音乐的男人~


    有童鞋不理解“自带运行环境”的含义~

    再举例说一次吧~

    码农们都吃过方便面吧~
    它和普通面条有什么区别呢?
    就是 自带调味包 。
    调味包就是方便面的烹饪环境。
    它简化了煮面条的流程。让用户不必练就厨艺也能吃上美味的内牛满面。

    函数式编程的闭包,就是函数的调味包。
    方便用户调用函数。不必为了维护繁杂的外部状态而烦恼。
    例如python,就把闭包玩出了很多花样:
    静态私有变量啦~
    偏函数啦~
    单参化~
    装饰器~
    ……

    当你在用这些功能的时候,其实就是在吃别人设定好调味包的“方便面”。

    其实我的理解:闭包的目的是用来扩大变量的作用域的。

    立即执行函数和闭包有什么关系

    重点看下@边城的理解,我的答案比较单薄,要是还感兴趣,可以看下高程三对作用域链、闭包这段的阐述~

    刚看的一篇文章 史上被骂最多的编程语言——JavaScript

    楼主的回答并不准确,如果我是面试官我也不满意。
    简单来说,闭包是指当函数被当成对象返回时,如果夹带了外部变量就形成了闭包。我非常赞同那位比喻把馒头加上馅变成包子的同学的回答,他虽是调侃成分居多,但理解的程度非常之深刻。

    如果一个函数打包了外部变量,就可以给程序非常大的灵活性,你可以把闭包理解成轻量级的接口封装,虽然对外都是这个函数(调用方式不变),但是因为之中的变量不一样,就可以完成很多功能。这也就是那位同学说的自带运行环境的函数,自带背景音乐的男人,想想都可怕。

    如果你想还深入了解一点,可以参考我总结的一篇文章,详解Python中的闭包,虽然编程语言不一样,但是道理是一样的。

    你的回答是关于作用域的回答,不是关于闭包的。而且这个回答也是属于不严谨的回答。你根本解释不清什么是内部,什么是外部。

    我认为闭包是这样的。当一个函数在定义它的作用域以外的地方被调用时,它访问的依然是定义它时的作用域。这种现象称之为闭包。

    具体用途有好多,常见的有创建私有属性,函数柯里化等等。

    ------------分割线------------

    我再补充一下,其实闭包的本质是静态作用域。因为 JavaScript 没有动态作用域,所以函数访问的都是定义时的作用域,所以闭包才得以实现。

    其他答案里说闭包是自带运行环境的函数。但是实际上,JavaScript 里任何函数不都是自带运行环境的函数吗?有的人也因此认为所有的函数都是闭包。这当然也不算错,但对理解闭包其实意义不大。因为你平时都是这么使用函数的,即使你不知道什么是闭包,也不会出什么问题。只不过平时你可能没有意识到全局作用域就是一个大闭包。

    我们常见的闭包形式就是a 函数套 b 函数,然后 a 函数返回 b 函数,这样 b 函数在 a 函数以外的地方执行时,依然能访问 a 函数的作用域。其中“b 函数在 a 函数以外的地方执行时”这一点,才体现了闭包的真正的强大之处。

    总之,闭包只是基于静态作用域的一个编程技巧。从面试的角度来说,你要回答什么是闭包,你首先得解释什么静态作用域的特点,然后还必须要强调“b 函数在 a 函数以外的地方执行时”这一点,才算是对闭包的完整回答。

    lambda演算式只允许单输入单输出,所以lambda a, b: a + b就等于lambda a: lambda b: a + b也就是currying。

    简单来说,闭包的定义是:函数能访问它被定义时的作用域。

    所以,你说的访问控制之类的,只是闭包的一个应用场景而已,当然没有回答什么是闭包的问题,面试官自然就不满意。

    另外,Java里面其实是不支持闭包的,匿名内部类看起来跟闭包差不多,但实际上不管是功能性还是实现层面都不能算是闭包。因为:

    1. 从功能上,匿名内部类里面访问的变量必须是final(Java8隐含声明final)

    2. 实现上,匿名内部类里访问的final变量值其实是从外面被拷贝进去了,所以其并不能真正访问到之前的作用域,这也是为什么必须是final的原因。

    所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
    在Javascript中创建一个闭包来解释闭包最好不过:

    function a(){
    var i=0;
    function b(){
    alert(++i);
    }
    return b;
    }
    var c=a();
    c();

    函数b嵌套在函数a内部;函数a返回函数b。
    这样在执行完var c=a( )后,变量c实际上是指向了函数b,再执行c( )后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,因为函数a外的变量c引用了函数a内的函数b,也就是说:当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

    其实按照闭包的一般写法形式,简单的来说就是 函数里面又嵌套了函数。在团队开发中,为了防止命名冲突,我们一般会把相应的代码用闭包的形式包裹起来,以避免暴露在全局作用域下面。但是有个不好的地方是其内部变量不会被立马回收,有内存溢出的风险。

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:java javascript php
    上一篇:strrchr截取空格 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 聊聊PHP escapeshellarg函数使用的中文问题• PHP原生类的总结分享• 分享PHP函数使用小工具(附代码示例)• PHP安全编码总结(经验分享)• 非常全面!PHP常见漏洞代码总结!
    1/1

    PHP中文网