21047
2156
这个问题的答案是社区的努力。编辑现有答案以改善此职位。它目前不接受新的答案或互动。
您将如何向了解了闭包本身的概念(例如函数,变量等)的人解释JavaScript闭包,但却不了解闭包本身?
我已经在Wikipedia上看到了Scheme示例,但是不幸的是它没有帮助。 
1个
2
3
下一个
闭包是以下内容的配对:
一个功能,以及
对函数外部范围的引用(词法环境)
词法环境是每个执行上下文(堆栈框架)的一部分,并且是标识符(即局部变量名称)和值之间的映射。
JavaScript中的每个函数都对其外部词汇环境保持引用。此引用用于配置调用函数时创建的执行上下文。此引用使函数内部的代码可以“查看”在函数外部声明的变量,而不管调用函数的时间和位置。
如果一个函数被一个函数调用,而另一个函数又调用了另一个函数,则将创建对外部词汇环境的引用链。该链称为作用域链。
在以下代码中,inner与调用foo时创建的执行上下文的词法环境形成一个闭包,从而对变量secret进行闭包:
函数foo(){
const secret = Math.trunc(Math.random()* 100)
返回函数inner(){
console.log(`秘密号是$ {secret}。`)
}
}
const f = foo()//无法从外部`foo`直接访问`secret`
f()//检索“秘密”的唯一方法是调用“ f”
换句话说:在JavaScript中,函数带有对私有“状态框”的引用,只有它们(以及在相同词法环境中声明的任何其他函数)可以访问。状态框对于函数的调用者是不可见的,从而为数据隐藏和封装提供了出色的机制。
请记住:JavaScript中的函数可以像变量一样传递(一流的函数),这意味着功能和状态对可以在程序中传递:类似于在C ++中传递类实例的方式。
如果JavaScript没有闭包,则必须在函数之间显式传递更多状态,从而使参数列表更长,代码更嘈杂。
因此,如果您希望函数始终有权访问私有状态,则可以使用闭包。
...而且我们经常想将状态与函数关联。例如,在Java或C ++中,当您将私有实例变量和方法添加到类时,您正在将状态与功能相关联。
在C语言和大多数其他常见语言中,函数返回后,所有本地变量将不再可访问,因为堆栈框架被破坏了。在JavaScript中,如果在另一个函数中声明一个函数,则外部函数从其返回后仍可访问。这样,在上面的代码中,机密在从foo返回后仍可用于函数对象内部。
闭包的使用
每当需要与函数关联的私有状态时,闭包都是有用的。这是一种非常常见的情况-请记住:JavaScript直到2015年才使用类语法,并且仍然没有私有字段语法。封闭件可满足此需求。
私有实例变量
在以下代码中,函数toString关闭了汽车的详细信息。
功能Car(制造商,型号,年份,颜色){
返回{
toString(){
返回`$ {manufacturer} $ {model}($ {year},$ {color})`
}
}
}
const car = new Car('Aston Martin','V8 Vantage','2012','Quantum Silver')
console.log(car.toString())
功能编程
在下面的代码中,函数inner关闭fn和args。
函数curry(fn){
const args = []
返回函数inner(arg){
if(args.length === fn.length)返回fn(... args)
args.push(arg)
返回内部
}
}
函数add(a,b){
返回a + b
}
const curriedAdd =咖喱(添加)
console.log(curriedAdd(2)(3)())// 5
面向事件的编程
在以下代码中,函数onClick关闭变量Background_COLOR。
const $ = document.querySelector.bind(文档)
const Background_COLOR ='rgba(200,200,242,1)'
函数onClick(){
$('body')。style.background =背景颜色
}
$('button')。addEventListener('click',onClick)