承诺是闭包吗?

15
闭包标签页面中写道:"jQuery 本身是一个大的闭包。" 但是 Promise 也是一个闭包吗?请说明原因。这就是我对闭包的理解:将函数赋值给变量并在不同的环境中重复使用它。Promise 使用 `$.ajax()` 实现了这一点,但我在 StackOverflow 中找不到任何介绍 Promise 是闭包的地方。可能是因为 Promise 还有其他功能,如 `$.Deferred()`、`resolve()` 和 `fail()`,可以扩展其功能以实现超越简单函数传递的效果吧?

1
我对闭包的理解略有不同(来自维基百科)。顺便说一句,好问题(+1)。 - Geeky Guy
@Renan:也许这应该是另一个问题,但如果有一个引用环境并且它可以根据函数的调用方式进行更改,我是否可以简化说“它与不同的环境一起使用?”据我理解,这对应于“函数可以访问其参数列表中没有的变量”。但由于我的无知,我可能在此处松散地使用了“环境”一词。您能否为我指出函数环境定义的参考资料?或者如果我在这里完全错过了重点,您能否简要描述一下为什么您的观点存在差异? - Forethinker
看看我的答案,引用将带您了解每个主题的精华。 - ars265
1
我觉得这可能更适合[Programmers.SE]。 - zzzzBov
@zzzzBov 你可能是对的,但每个人都知道一些基础知识以便更好地理解是很好的。 - ars265
@Forethinker 这应该是另一个问题,我认为如果你去查找,你会发现它已经在 Stack Overflow 中得到了回答。 - Geeky Guy
4个回答

17

闭包

我对闭包的理解是:将函数赋值到变量上,并在不同的环境中重复使用。

这并不是严格准确的闭包定义。

闭包指的是具有引用环境访问权限的函数。在JavaScript中,这意味着一个函数由另一个函数返回,并且可以访问原始函数的作用域。其他SO问题描述了这一点得非常好

闭包是通用结构,可以以各种方式使用。它们最大的好处之一是保护私有作用域,这也是为什么像jQuery这样的库经常被编写为闭包形式,以便不需要将所有函数全局暴露。

Promise

Promise是一种不同的概念。它们是一种组织异步代码的方式,使其更易于遵循流程。特别地,promise对象是提供了按清晰易读的方式链接操作的对象。一个Promise可能使用闭包实现,但不必如此。例如,下面是一个不使用闭包的实现:

https://gist.github.com/814052/690a6b41dc8445479676b347f1ed49f4fd0b1637

而jQuery的实现使用至少一个闭包,但并不是基于它们的。

http://james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.Deferred

结论

Promise(承诺)和Closure(闭包)不是直接相关的概念。 Closure(闭包)是一种编程技巧,可能会在Promise(承诺)的实现中使用。最终,实现Promise(承诺)并非不可能或不必像这样。


谢谢你的直截了当的回答。 - Forethinker
这让我面临着我来这里的问题:闭包如何在Promises中使用?当我使用Promises时,有时我希望从各种先前的Promises将值隐式地发送到then函数。请参见https://dev59.com/3l4c5IYBdhLWcg3wJnf8#57681704的结尾,了解我使用'bind'显式创建的闭包的解决方案。 - David Spector

6

即使您用2x4制作鸟屋,您也不会问它是否是一个鸟屋。承诺和闭包也是如此。承诺利用闭包来保留对状态、回调和其他类似事物的引用。


5
因为 JavaScript 的异步特性,我们可以通过语言和运行时提供的强大功能。首先,在 jQuery 中,一个 Promise 对象,虽然它不是 jQuery 特有的,但是根据文档,它是一个对象,观察绑定到集合的某种类型的所有操作(排队或未排队)何时完成。这意味着您可以使用此对象来了解何时在一组项目的行为完成后继续进行操作。另一方面,闭包并不是 jQuery 特有的,而是一种 JavaScript 构造,将两个东西结合在一起:一个函数和创建该函数的环境。这意味着不仅执行函数,还可以在可能完全不同的上下文中执行函数。

Promise(承诺)在jQuery中并非独有的。http://wiki.commonjs.org/wiki/Promises/A - Ben McCormick
不,他们不是,但他提到了jQuery,所以我这样回答。主要的重点是它们的定义,我已经尽力阐述了。我在我的答案中添加了这一点来帮助说明。 - ars265

2

闭包和Promise是不同的概念。闭包指的是变量的作用域,而Promise则用于“承诺”在异步操作完成时将对某个对象进行操作。由于Javascript是非阻塞的(而不是异步的--编辑),如果它需要访问互联网或磁盘,则不会等待函数获得响应,也就是说,您可以在某些操作完成后执行Promise。


1
我对这个答案一直都很满意,直到 "由于JavaScript是异步的()..." - Geeky Guy
抱歉,我是指非阻塞的……如果有异步操作,它将不会等待响应。 - Borrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接