Javascript 这个函数在这个块上有闭包吗?

Javascript 这个函数在这个块上有闭包吗?,javascript,closures,Javascript,Closures,我正在试验闭包,但不是将函数封装在函数中,而是将函数封装在块中。由于函数没有阻塞作用域,并且将被提升到块的外部,所以我假设它不会访问块内的作用域。然而,在本例中,函数返回块作用域变量。这是否意味着函数是一个闭包 { let a = 'hi' function test() { return a } } test() // hi 我很乐意称之为结束,至少根据WikMedia的定义: 在操作上,闭包是一个记录,它将一个函数与一个环境一起存储。环境是一种映射,将函数的每

我正在试验闭包,但不是将函数封装在函数中,而是将函数封装在块中。由于函数没有阻塞作用域,并且将被提升到块的外部,所以我假设它不会访问块内的作用域。然而,在本例中,函数返回块作用域变量。这是否意味着函数是一个闭包

{
   let a = 'hi'
   function test() {
      return a
   }
}
test() // hi

我很乐意称之为结束,至少根据WikMedia的定义:

在操作上,闭包是一个记录,它将一个函数与一个环境一起存储。环境是一种映射,将函数的每个自由变量(本地使用但在封闭范围内定义的变量)与创建闭包时名称绑定到的值或引用相关联。与普通函数不同,闭包允许函数通过闭包的值或引用副本访问这些捕获的变量,即使函数在其作用域之外调用

在函数
test
中,变量
a
是一个自由变量,由函数使用,但未在函数内部定义。在块外调用函数时,它保留了
a
的值。因此,您已经了解了闭包定义的要点(根据维基百科)

当然,你问这个问题是因为它有点棘手。通常使用闭包,我们在环境中定义一个函数,然后通过将函数对象绑定到范围更广的名称来“导出”它。由于JavaScript处理块中定义的函数声明的方式(参见CodeManiac关于处理块作用域函数声明的ECMAScript规范链接),您确实得到了这种效果!所以这是一种闭包,即使您从未显式导出函数

当然,如果你写过

{
   let a = 'hi'
   let test = () => a
}
test()
你会得到一个错误

但这是可行的:

let b;
{
   let a = 'hi'
   let test = () => a
   b = test
}
b() // "hi"

因此,是的,块作为非局部环境,可以从中捕获变量。我认为是的,可以将其称为闭包,因为它的行为类似于闭包(即使此行为来自ECMAScript 2015之前的“可选”以及对块内函数声明的非严格处理)。如果它像鸭子一样移动,等等。

对于遗留代码的兼容性,我们有一些相关的和这些链接,非常棒,谢谢你指出它们。你的编辑器应该告诉你不应该在块中声明函数。从技术上讲,每个函数在JS中都是闭包,由于每个函数都有一个对它在其中创建的环境的引用,所以在块中声明函数绝对没有错。(不使用strict模式有一个问题)从技术上讲,每个函数在JS中都是闭包,因为每个函数都有一个对创建它的环境的引用。函数在何处/何时执行并不重要。甚至规范在函数定义的上下文中也使用了术语“闭包”。我同意人们似乎将不同的含义与该术语联系在一起,但我也从未见过权威文本说需要在创建环境之外调用函数,才能将其称为closure shrug.Fair。我同意耸耸肩。至少斯威夫特在使用术语闭包时更诚实(更明确),将术语定义为比函数更广泛的东西(任何“可以传递和使用的自足功能块”),是的,甚至说所有函数都是闭包许多人确实保留了自由变量函数的术语,这些函数将在定义它们的环境之外使用,我认为这就是OP提出的精神,但是,是的,所有JS函数也都是闭包。干杯。“这种行为来自ECMAScript 2015之前的一个“可选”,因此,考虑到这一点,这种类型的闭包会被建议反对吗?我会说是的。事实上,围绕块级函数声明存在一些问题,而且它们的语义并不明显,我认为这是避免它们的好理由。