Javascript 函数返回是否需要称为闭包

Javascript 函数返回是否需要称为闭包,javascript,closures,Javascript,Closures,嘿,我在youtube上看到了这个视频 这基本上解释了IIFE和闭包。但我不明白的是,我是否需要返回一个函数才能将其称为闭包 E.x 在这种情况下,当它从外部函数的作用域访问'i'变量时,我可以称它为闭包,还是需要像这样返回函数 return function b(){alert(i);} 返回函数不会改变任何东西,重要的是创建并调用它。这就形成了闭包,即从内部函数到创建它的作用域的链接(实际上,你可以把它看作一个指针。例如,它具有防止外部作用域被破坏的相同效果)。通过,从函数到其包含作用域的

嘿,我在youtube上看到了这个视频

这基本上解释了IIFE和闭包。但我不明白的是,我是否需要返回一个函数才能将其称为闭包

E.x

在这种情况下,当它从外部函数的作用域访问'i'变量时,我可以称它为闭包,还是需要像这样返回函数

return function b(){alert(i);}

返回函数不会改变任何东西,重要的是创建并调用它。这就形成了闭包,即从内部函数到创建它的作用域的链接(实际上,你可以把它看作一个指针。例如,它具有防止外部作用域被破坏的相同效果)。

通过,从函数到其包含作用域的链接就足够了。因此,创建函数基本上就是一个闭包,因为在JavaScript中创建链接的地方:-)

然而,为了利用这一特性,我们确实从不同的范围调用了函数,而不是在中定义的-这就是“使用闭包”在实践中所指的术语。这既可以是较低的范围,也可以是较高的范围-函数不一定需要从中定义的函数返回

一些例子:

var x = null;

function a() {
    var i = "from a";
    function b() {
        alert(i); // reference to variable from a's scope
    }
    function c() {
        var i = "c";
        // use from lower scope
        b(); // "from a" - not "c"
    }
    c();

    // export by argument passing
    [0].forEach(b); // "from a";
    // export by assigning to variable in higher scope
    x = b;
    // export by returning
    return b;
}
var y = a();
x(); // "from a"
y(); // "from a"

实际闭包是变量的容器,因此函数可以使用创建它的范围中的变量

返回函数是在创建函数的不同范围内使用函数的一种方法,但更常见的用法是当它是来自异步调用的回调时

函数使用一个作用域中的变量,而函数在另一个作用域中使用的任何情况都使用闭包。例如:

var globalF; // a global variable

function x() { // just to have a local scope

  var local; // a local variable in the scope

  var f = function(){
    alert(local); // use the variable from the scope
  };

  globalF = f; // copy a reference to the function to the global variable

}

x(); // create the function
globalF(); // call the function

(这只是一个闭包的演示,让一个函数设置一个全局变量,然后使用它并不是编写实际代码的好方法。)

闭包只是一个保持词法环境的函数,直到它自己死了才放手

把结束想象成史克鲁奇叔叔:

史克鲁奇叔叔是个守财奴。他永远不会放弃他的钱

同样,闭包也是守财奴。它不会放弃它的变量,直到它自己死去

例如:

function getCounter() {
    var count = 0;

    return function counter() {
        return ++count;
    };
}

var counter = getCounter();
var counter;

function setCounter() {
    var count = 0;

    counter = function counter() {
        return ++count;
    };
}

setCounter();
查看该函数
计数器
getCounter
函数返回的值?那个职能部门是个守财奴。即使
count
变量属于
getCounter
函数调用且该函数调用已结束,它也不会释放
count
变量。因此,我们称计数器为闭包

请参见每个函数调用都可能创建变量。例如,对
getCounter
函数的调用将创建一个变量
count
。现在,这个变量
count
通常在
getCounter
函数结束时消失

但是,
counter
函数(可以访问
count
变量)不允许在调用
getCounter
结束时终止。这是因为
计数器
功能需要
计数
。因此,它只允许
count
在自身死亡后死亡

现在值得注意的是,
counter
在对
getCounter
的调用中诞生。因此,当对
getCounter
的调用结束时,即使是
counter
也应该停止,但它没有停止。即使在对
getCounter
的调用结束后,它仍然存在,因为它超出了
getCounter
的作用域(生存期)

counter
有许多方法可以跳出
getCounter
的范围。最常见的方法是
getCounter
简单地返回
counter
。然而,还有更多的方法。例如:

function getCounter() {
    var count = 0;

    return function counter() {
        return ++count;
    };
}

var counter = getCounter();
var counter;

function setCounter() {
    var count = 0;

    counter = function counter() {
        return ++count;
    };
}

setCounter();
这里,
getCounter
的姐妹函数(恰当地称为
setCounter
)为全局
计数器
变量分配一个新的
计数器
函数。因此,内部
计数器
函数脱离了
setCounter
的作用域而成为闭包

实际上,在JavaScript中,每个函数都是闭包。然而,直到我们处理超出父函数范围的函数时,我们才意识到这一点,并且即使在对父函数的调用结束后,仍然保持属于父函数的某些变量处于活动状态


欲了解更多信息,请阅读此答案:

下面是一组关于闭包的解释。对我来说,《老虎书》中的那本最让我满意…隐喻的书也很有帮助,但只有在遇到这本书之后

  • 闭包:在集合论中,闭包是一个(最小的)集合,在这个集合上,一些操作产生的结果也属于这个集合,所以它有点像“在某些操作下最小的封闭社会”
a) sicp:在抽象代数中,如果将运算应用于集合中的元素会产生一个元素,而该元素又是集合中的元素,则称一组元素在一个运算下是闭合的。Lisp社区还(不幸地)使用“闭包”一词来描述一个完全不相关的概念:闭包是一种用自由变量表示过程的实现技术

b) wiki:闭包是第一类函数,它在定义环境中捕获自由变量的词法绑定。一旦捕获了词法绑定,函数就成为一个闭包,因为它“关闭”了这些变量

tiger book:堆上(而不是堆栈上)的数据结构,包含函数指针(MC)和环境指针(EP),表示函数变量

d) 在lisp上:函数和一组变量绑定的组合称为闭包;闭包是本地状态的函数

e) google i/o视频:类似于类的实例,其中数据(实例obj)封装代码(vtab),在闭包的情况下,代码(函数变量)封装d