【问题标题】:Why does this javascript code returns 3 as counter value?为什么这个 javascript 代码返回 3 作为计数器值?
【发布时间】:2019-09-24 21:23:28
【问题描述】:

所以,最近我一直在尝试学习 javascript,结果遇到了这段代码

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

add();
add();
add();

通过执行此操作,计数器变为 3。但是有些事情我很难理解。比如 return function 语句在做什么?对我来说,似乎在函数内部返回了另一个匿名函数。但我不知道这段代码是如何工作的。几个小时以来,我一直在努力理解这一点。

这是另一个代码:

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

// Call add() 3 times
add();
add();
add();

但它返回计数器值为 1(我理解),那么为什么前面的代码返回 3。我需要深入的解释。我花了几个小时在 w3schools、mdn 文档和 youtube 教程上学习闭包,我想我已经理解了闭包(至少是其中的一部分)。但我无法理解这段代码。所以,我真的需要你的帮助。谢谢。

【问题讨论】:

  • 在第一个示例中,计数器存储在闭包中,在第二个示例中,您每次执行 add 时都会创建一个新的计数器变量
  • 这里是closures的一些文档

标签: javascript closures


【解决方案1】:

在您的第一个示例中,您正在创建一个立即调用的函数表达式 (IIFE)。 add 变量被初始化为函数调用的返回。在这种情况下,add 等于 function() { counter += 1; return counter; }

最后计数器为 3 的原因是因为在 IIFE 中,您使用变量 counter 创建了一个本地范围。此变量只能在该范围内访问。因此,如果您在调用add() 后尝试访问counter,它将不存在。

在第二个示例中,每次调用 add() 时,都会在本地范围内创建一个新变量。所以每个电话都从0开始。

您可以在此处阅读有关范围的更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Differences

如果您想要与第二个示例中的 IIFE 相同的功能,您可以简单地在函数外部声明 counter 变量。

let counter = 0;
const add = () => ++counter;
add();
add();
add();

或者,您可以传入要递增的变量。

let counter = 0;
const add = (increment) => ++increment;
counter = add(add(add(counter)));

【讨论】:

  • 谢谢你的回答,伙计。所以我开始明白这一点了。但是,我有一个问题。如果没有返回函数的返回,我们能否在第一个代码中实现相同的输出?如果是这样,如何?我尝试简单地删除 return 并只留下函数,但没有奏效。问是因为从未见过以这种方式使用的回报。所以如果你能解释一下,那将非常有帮助。谢谢
  • @ZainAbedin 当然,我更新了我的答案以展示你如何做到这一点。出于好奇,您想完成什么?
  • 哦,谢谢。我刚读过。我没有写代码,我只是在 w3schools 网站上阅读关于闭包的内容,偶然发现了这段代码,真的无法理解,所以在这里询问
  • 当然可以。基本上外部函数被立即调用,结果是一个存储在变量add中的函数
  • 哦,好吧。非常感谢帮助的人。我要精神了。现在,我了解了工作原理,非常感谢你,伙计。
【解决方案2】:

您可以在MDN 中阅读有关 JavaScript 闭包的更多信息。

共享词法环境是在一个匿名函数的主体中创建的,它在定义后立即执行。词法环境包含名为counter 的私有变量。无法从匿名函数外部直接访问私有变量。相反,它们必须由匿名包装器返回的公共函数访问。

【讨论】:

  • 哦,好吧。感谢你的回答。您能解释一下代码 1 第 3 行中的返回函数吗?因为我从未见过它在使用中,当我尝试用谷歌搜索时,它只告诉我返回声明
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-06
  • 2013-08-24
  • 2014-09-20
  • 2019-06-23
  • 2021-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多