一个在全局作用域中声明的函数是一个闭包吗?

3

我正在为一份JavaScript开发工程师的面试做准备,我遇到了这个闭包的定义:

闭包是一个在另一个函数(称为父函数)中定义的函数,并且可以访问在父函数作用域中声明和定义的变量。

我们来看两段不同的代码:

function a() {
    const temp = 1;

    function b() { 
        console.log(temp); 
    }        
}  

很明显,函数b是一个闭包,因为它是在函数a内声明的,并且可以访问它的变量temp

但如果我只是这样声明一个函数,而没有使用IIFE:

function c() {
    alert("Hi") // a function taken from the global scope
}

我的c函数没有在任何函数内声明,但它可以访问全局范围。它可以被称为闭包吗?还是必须特别在另一个函数内声明才能被称为闭包?


2
也许有一些我没有考虑到的特殊情况,但据我所知,从技术上讲,你声明的每个函数都是一个闭包。通常只有在你想强调它访问了其父作用域中声明的变量时,才会称之为闭包。 - ASDFGerte
闭包有三个作用域链,它拥有自己定义的变量、封闭函数的变量以及全局变量。你的第二个例子只有局部和全局作用域链,所以不,它不是一个闭包。 - James
1
我对规范的了解还不够深入,无法确定我的答案是否正确。然而,根据我所阅读的内容,ECMAScript函数对象封装了基于词法环境的参数化ECMAScript代码,并支持对该代码的动态评估。全局环境是一个没有外部环境的词法环境。 - ASDFGerte
1
@James,只有一个作用域链。作用域链上可能有来自多个执行上下文的变量。 - RobG
1
那个对闭包的定义是错误的,请参考MDN上的定义(注意,MDN并不是权威机构,但它是一个非常有用的资源)。每个函数都会创建一个闭包来访问其外部上下文中的变量。当闭包在创建它的函数的生命周期之外仍然存在时,它们变得更加有趣,但这并不是创建闭包的必要条件。 - RobG
1个回答

5
可以称之为闭包,但我会说它创建了一个闭包(针对其外部执行上下文中的变量),而不是“是”一个闭包。
不需要特别在另一个函数内声明才能被称为闭包。
重复问题,请参考:How do JavaScript closures work?

那么很明显,我遇到的定义是错误的,对吗? - user5466293
2
@AdrianWydmanski——是的。通常在同一上下文中介绍闭包,如Douglas Crockford的文章《JavaScript中的私有成员》(http://javascript.crockford.com/private.html)。然而,尽管闭包的这个方面最有趣(即它们能够在创建它们的函数的生命周期之外持久存在),但这并不是它们创建的必要条件。 - RobG

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