闭包为什么叫闭包

2020-10-06 16:47:50 +08:00
 zxCoder

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

5587 次点击
所在节点    JavaScript
18 条回复
Cbdy
2020-10-06 16:55:15 +08:00
是的
有一些用
不是
没有关系
des
2020-10-06 16:59:33 +08:00
闭包又叫词法闭包,至于“闭包”这个词是翻译自英文 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
2020-10-06 17:03:29 +08:00
@des 补充一下参考资料,顺便“闭包”这个描述应该是源于数学

https://www.zhihu.com/question/422554486
https://www.zhihu.com/question/333567126/answer/742694242
geelaw
2020-10-06 17:12:49 +08:00
https://i.loli.net/2020/10/06/h6lNvGms2EU7DjS.png

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

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

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

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

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

现在 JS 的闭包算是一种语法糖吧,有需求且闭包特性正好满足需求就可以用,没有需求就不用。
Metaki
2020-10-28 08:39:40 +08:00
局部变量不想让外面访问,但想让自己访问,类似面向对象中的 private
ConnJiang
2020-12-08 20:46:23 +08:00
闭包 = 自由变量 + 函数

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/712785

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX