JavaScript闭包澄清?

5

尽管我读了很多文章,但仍然有一些问题。

我已经知道(并理解)闭包的用法,比如:

  1. 臭名昭著的Loop问题(链接循环,每个链接都有警报,并保留编号)

  2. 增加计数器(不断调用一个函数 -> 警报增加的数字)

来自这里

内部函数引用其外部函数的局部变量会创建闭包

来自这里

闭包是函数的本地变量-在函数返回后保持活动状态,或者闭包是未在函数返回时取消分配的堆栈帧。(就像“堆栈帧”被malloc而不是在堆栈上!)

3个问题:

问题#1

有人告诉我JS中所有的函数都会创建闭包。

什么?如果我创建一个带有私有变量的普通函数,它只会创建作用域,而不是闭包。

我认为闭包的工作方式是这样的:(来自这里)

  1. 创建一个外部“函数制造器”函数。
  2. 在其中声明一个局部变量。
  3. 在外部函数内声明一个内部函数。
  4. 在内部函数中使用外部函数的变量。
  5. 让外部函数返回内部函数
  6. 运行该函数,并将其返回值分配给一个变量

示例:

function functionMaker(){
   var x = 1;
   function innerFunction(){
     alert(x);
     x++;
   }
   return innerFunction;
}

那么为什么他们说每个js函数都创建闭包?

问题 #2

自执行函数,又称IEFA(立即调用函数表达式),是否会创建一个闭包?

看一下:

(function (a) {
    alert(a);
})(4);

我并没有看到像上面提到的那样的“6条规则”模式: “将外部函数返回内部函数”的部分在哪里?我没有看到“return”这个单词。
第三个问题。
function myFunction() {
  var myVar = 1;
  var alertMyVar = function () {
    alert('My variable has the value ' + myVar);
  };
  setTimeout(alertMyVar, 1000 * 3600 * 24);
}
myFunction();

我的函数 myFunction 一直存在吗?还是在 setTimeout 后立即结束了?如果是,SetTimeOut 是如何“记住”那个值的?

请帮我理解正确。

1个回答

8
所有函数调用都会创建一个闭包。需要注意的重要事项是闭包是否超出了函数调用的生命周期。
如果我执行一个立即执行的函数:
var value = (function() {
  return 4;
})();

这时将创建一个闭包,但随着函数返回闭包将被舍弃。为什么呢?因为没有任何指向在闭包中定义的符号的存活引用。但是在这里:

var value = function() {
  var counter = 0;
  return function() {
    return counter++;
  };
}();

闭包在立即执行函数执行后仍然存在,因为它返回了另一个函数,而该函数反过来包含对原始函数中定义的"counter"符号的引用。由于返回的函数仍然"存活",所以运行时系统必须保留闭包。

请注意,在这里:

var value = function() {
  return function(a) {
    return "hello " + a;
  };
}();

尽管外层立即执行函数返回一个函数,但该函数没有引用来自外层的任何符号,因此没有必要保留闭包。我想我想说的是,将闭包视为执行函数的一部分效果会很有帮助,而不仅仅是作为静态结构的一部分。有可能存在一个函数,有时创建一个持久闭包,但并非总是如此。

2
@WaleedKhan 不,那不是真的。只有在function关键字需要消除歧义时才是必要的。在等号表达式的右侧没有歧义,因此括号是不必要的。 - Pointy
@Pointy(请听我说)-如果我和工作中的朋友争论 - 通过说“这不是闭包”(就像你的第一个例子一样),而这确实是闭包(记住状态-就像你的第二个例子一样)-我应该告诉他什么?它是闭包但不是________(我正在寻找专业术语)。 - Royi Namir
嗯,也许可以考虑内存分配/垃圾回收方面的问题。如果您创建了一个对象,那么当没有变量包含对该对象的引用时,它可以被垃圾回收器回收。闭包就像这样 - 如果没有任何对闭包中声明的内容的引用,它可以被垃圾回收;否则,它不能。 - Pointy
@Pointy 你好。我很高兴从你那里得到关于https://dev59.com/WGYr5IYBdhLWcg3wpbyQ的答案。 - Royi Namir
闭包能用于引用类型吗?请查看此帖子http://stackoverflow.com/questions/20790386/javascript-closures-and-object-reference/20790832 - mobygeek
显示剩余10条评论

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