【问题标题】:What does "return () => local;" do in this closure?“return () => local;”是什么意思?在这个闭包中做什么?
【发布时间】:2019-05-20 12:11:39
【问题描述】:

我正在通过阅读“Eloquent Javascript”来学习 javascript,但对第 3 章(函数)中的“闭包”部分感到困惑。

在前面的部分中,我了解了箭头函数,以及如何将它们用作匿名函数。我最初的想法是,这是一个匿名函数示例,我还不熟悉。

特别是,我对“() => local”对/返回的作用感到困惑。

function wrapValue(n) {
  let local = n;
  return () => local;
}

let wrap1 = wrapValue(1);
let wrap2 = wrapValue(2);
console.log(wrap1());
// → 1
console.log(wrap2());
// → 2

以下是该章节的链接: Eloquent Javascript - Ch. 3 "Functions"

提前致谢!

【问题讨论】:

  • 只是一个函数,调用时返回变量local。闭包的重点是变量 local 设置在外部函数中,但即使在 wrapValue 返回之后,它仍然在返回函数的范围内。
  • 看起来像const wrap1 = 1; 的复杂方式。
  • @RobG - 不复杂,它是“雄辩的”:D
  • @MarkMeyer 哦,好的,我明白了。所以这只是简单地返回通过将 n 分配给本地给出的任何内容,然后返回本地。确实很纠结!哈哈 那我为什么不直接使用“返回本地”呢?
  • @Tucker 你可以,但它不会演示在 wrap 函数返回后如何仍然可以访问变量。

标签: javascript return closures


【解决方案1】:
function wrapValue(n) {
   let local = n;
   return () => local;
}

和写一样(没有“this”的好处)

function wrapValue(n) {
   let local = n;
   return function() {
        return local;
   }
}

它是一个返回另一个使用传递参数的函数的函数。这称为Curry function

console.log(typeof wrapValue(2)); // prints "function"
console.log(wrapValue(2)()); // prints "2"

这是一个更好的例子

function multiple(a) {
    return (b) => a*b;
}

console.log([1,2,3,4].map(multiple(2)); // prints "[2,4,6,8]"

您可以通过数组非常轻松地使用柯里化函数

【讨论】:

  • 我认为这实际上并不是柯里化。正如您链接到的文章所说,如果将一个接受多个参数的函数转换为一个接受一个参数并返回一个函数的函数,则柯里化是一个过程。 multiple 在这里没有柯里化,它已经是一个接受单个参数的函数。所以它只是一个高阶函数?或者我对柯里化的理解是不正确的......
  • 对于第二个“function()”版本,内部函数是否仍然能够访问父函数范围内的“本地”变量?还是这两者的区别?
  • @FelixKling multiple 有 2 个参数,但每个参数都有自己的功能。高阶函数是每个参数都是一个函数,它返回另一个函数。
  • @Tucker:答案说“和写作一样(没有“this”的好处)”...
  • @FelixKling 抱歉,我还没有进入关于“this”及其功能的章节。
【解决方案2】:

在 javascript 函数中创建作用域。例如:

function scoped(){
  let local = 10;
  console.log(local) // this works local is within scope
}

scoped() // logs:

console.log(local) // error -- local doesn't exist out here.

scoped 之外的 local 不存在。

函数内的函数可以访问整个作用域。所以这行得通:

function scoped() {
  let local = 10;
  function f() {
    console.log(local) // this works local is within scope
  }
  f()
}

scoped()

但是如果你返回引用函数范围的函数会发生什么?事实证明,内部函数承载了整个作用域。这是一个闭包:

function scoped(){
  let local = 10;
  function f(){
    console.log(local) // this works local is within scope
  }
  return f
}

f = scoped()
f() // can still see local

// but nobody else out here can:
console.log(local) // still an error

这允许你做一些非常巧妙的事情——一个重要的事情是你可以将某些变量保持私有,但仍然可以使用闭包来操作它们。

例如,这里的计数器不需要全局范围内的变量:

function counter(){
  let count = 0
  return () => count++
}

let c = counter()

console.log(c())  // it can count but there's not count variable in scape
console.log(c())
console.log(c())

使用全局计数变量执行此操作会很麻烦,并且可能会导致代码的其他部分与全局变量发生冲突。上面,除了c 函数之外没有任何东西可以访问计数器。事实上,你可以制作几个独立的:

function counter(){
  let count = 0
  return () => count++
}

let c = counter()
let d = counter()

console.log("c:", c())  // it can count but there's not count variable in scape
console.log("c:", c())
console.log("d:", d())  // d has it's own closure
console.log("d:", d())
console.log("c:", c())

你可以用闭包做很多事情,它们在 Javascript 中很重要。花时间真正了解它们是值得的。

【讨论】:

  • 啊啊啊啊,我想它现在点击了。如果我错了,请纠正我,但我从中得到的是,通过闭包,我有能力在某种意义上提升价值的范围。因此,与其将变量值限制在其函数的范围内,我可以在该函数中使用 Closer 函数,然后独立于 OUTER 函数调用 INNER 函数——这将利用外部函数的范围变量并在某种意义上提升更高范围的值(或至少使这些值对/在不同范围有用)?
  • 是的@Tucker,这对我来说很有意义。我认为它更像是内部函数能够隐藏外部函数的范围并随身携带。允许它在没有其他人访问它的情况下使用它。
  • 这完全澄清了它。非常感谢马克!顺便说一句很酷的摄影! :)
  • 所有函数都在其外部范围内创建变量的闭包。只是通过返回一个函数来保持闭包使它们变得有趣。
猜你喜欢
  • 1970-01-01
  • 2011-07-12
  • 2016-01-24
  • 2021-05-25
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 2017-03-02
  • 2022-01-09
相关资源
最近更新 更多