V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
zxCoder
V2EX  ›  JavaScript

闭包为什么叫闭包

  •  
  •   zxCoder · 292 天前 · 3864 次点击
    这是一个创建于 292 天前的主题,其中的信息可能已经有所发展或是发生改变。

    学到闭包这个概念,就是函数返回一个函数,然后可以访问外层函数的局部变量? 这个有什么用吗?都是局部变量了,难道不就是为了不让外面访问的吗? 这跟数学上的闭包有什么关系吗?

    18 条回复    2020-12-08 20:46:23 +08:00
    Cbdy
        1
    Cbdy   292 天前 via Android
    是的
    有一些用
    不是
    没有关系
    des
        2
    des   292 天前
    闭包又叫词法闭包,至于“闭包”这个词是翻译自英文 Closure
    用来指代某些其开放绑定(自由变量)已经由其语法环境完成闭合(或者绑定)的 lambda 表达式,从而形成了闭合的表达式,或称闭包
    https://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)
    des
        3
    des   292 天前
    @des 补充一下参考资料,顺便“闭包”这个描述应该是源于数学

    https://www.zhihu.com/question/422554486
    https://www.zhihu.com/question/333567126/answer/742694242
    geelaw
        4
    geelaw   292 天前
    https://i.loli.net/2020/10/06/h6lNvGms2EU7DjS.png

    另一个类比:匿名函数 = CPU (提供逻辑),匿名函数所捕捉的变量 = 主存等其他设备(提供环境),闭包 = 可以使用的电脑。
    gbin
        5
    gbin   292 天前 via Android
    外层函数返回的函数运行时不确定,闭包是为了在外层函数执行完毕后垃圾回收时保存返回的函数需要读取的哪些局部变量。
    az467
        6
    az467   292 天前
    直接的关系好像没有。
    不过我觉得存在第三个词,这个词跟离散上的闭包还有编程上的闭包都有关系。
    Sinksky
        7
    Sinksky   292 天前 via Android   ❤️ 2
    编程上的闭包和数学上的闭包有些不同,编程上的闭包是保存有创建闭包时状态的函数(C++中叫捕获变量),数学上的闭包讲的是运算对于运算域封闭。
    vvxex
        8
    vvxex   292 天前 via iPhone
    闭包,就是带运行时环境的函数。over
    codingguy
        9
    codingguy   292 天前
    const accessConf = (function generateAccessor() {
    const config = '无法修改的值';

    return () => {
    return config;
    };
    })();

    accessConf(); // => '无法修改的值'

    这是一种使用场景。可以确保 config 只读。
    zxCoder
        10
    zxCoder   292 天前
    @codingguy 非杠,但是这样大费周章就是为了让 config 只读。。。 是否还有更加复杂的用处呢
    retanoj
        11
    retanoj   291 天前 via iPhone
    @zxCoder
    对于 js 而言,在没有 class 的时候,还想要实现像类一样的方法和私有变量的话,是不是就可以用闭包?
    12tall
        12
    12tall   291 天前
    称之为高阶函数更形象一些,个人觉得在 js 里面最直观的例子可以通过设置参数生成不同的线性插值函数
    wei771783057
        13
    wei771783057   291 天前 via iPad
    严格意义上讲,闭包只有一条定义就是 函数引用了外部变量 。
    所以其实你平常普通函数只要引用了全局变量就形成闭包了,只不过这是全局层面的,
    而一般的形式是 1,一个包裹函数内的函数引用了这个包裹函数内部词法作用域它自身外的变量,如果在包裹函数内这个函数直接就运行了,那就是形成了调用执行栈,然后执行完立马出栈 等垃圾回收 GC 后引用的变量内存就清理掉了,2,但我们一般狭义上闭包指的是包裹函数把这个内部函数返回赋给其他变量,但由于这个内部函数它引用了包裹内它自身外部作用域变量,导致在执行栈依次进出后,被引用的包裹内部变量无法被 GC,这就形成了所谓闭包。
    一般作用
    1,形成内部私有变量,无法被直接访问,必须通过引用它的内部函数获取,可以进行一系列读写访问控制。
    2,制作偏函数,比如 bind,可以接受一些预设参数值,返回一个会用到它们的函数,还有类似的像柯里化,将一个接受多个参数的函数转换成接受单一参数并返回一个接收剩余参数返回结果的函数。
    3,高阶函数,像组合函数 compose,把函数作为参数传入,内部实现其调用形式返回结果,还有像制作防抖节流函数也都是闭包的应用 都是通过预设的参数作为闭包变量返回一个引用它的函数来实现的功能。
    另外 class 类私有字段还在 tc39 提案中,不过 class 还是不太受待见,毕竟只是 prototype 的语法糖而且并不完备,js 社区感觉还是更偏向 FP 一些,,,
    codingguy
        14
    codingguy   288 天前
    @zxCoder 更复杂的用处想不到了,比如函数柯里化(实现看这里 https://hackernoon.com/currying-in-js-d9ddc64f162e )?
    基本都是用了可以直接访问外层代码块变量的这一便利。
    #13 总结的挺好
    wei771783057
        15
    wei771783057   287 天前 via iPad
    @codingguy 这个帖子写得很好
    libook
        16
    libook   286 天前
    计算机内的大多概念都是来源于数学,但是含义可能需要对照计算机的原理来解释,所以最好去了解一下 ES6 前后 JS 语言极其引擎究竟发生了哪些变化,以便于理解为什么过去存在闭包这个概念。

    JS 的块级作用域和 const 指令是 2015 年开出现的,class 的私有变量到现在还没到 Stage4,早期的 JS 特性是非常简单的,想要控制对变量的访问用闭包是最简单的方案,大多情况下也就只是想让变量只读,或者常驻内存不被 GC 回收。

    现在 JS 的闭包算是一种语法糖吧,有需求且闭包特性正好满足需求就可以用,没有需求就不用。
    Metaki
        17
    Metaki   271 天前
    局部变量不想让外面访问,但想让自己访问,类似面向对象中的 private
    ConnJiang
        18
    ConnJiang   229 天前
    闭包 = 自由变量 + 函数
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2575 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 04:51 · PVG 12:51 · LAX 21:51 · JFK 00:51
    ♥ Do have faith in what you're doing.