What does “return () => local;” do in this closure?

风格不统一 提交于 2021-01-22 07:17:27

问题


I'm learning javascript by reading "Eloquent Javascript" and am confused by the "Closures" section in chapter 3 (Functions).

In previous sections I learned about arrow functions, and how they can be used as anonymous functions. My initial thoughts were that this is an anonymous function example and I am simply not familiar yet.

In particular, I am confused on what "() => local" does to/for return.

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

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

Here is a link to the chapter: Eloquent Javascript - Ch. 3 "Functions"

Thanks in advance!


回答1:


In javascript function create scope. For example:

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.

Outside of scoped local doesn't exist.

A function inside a function has access to the entire scope. So this works:

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

scoped()

But what happens if you return that function that references the scope of the function? It turns out that the inner function carries the whole scope with it. This is a closure:

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

This allows you to do some very slick things — an import one is that you can keep certain variables private, but still manipulate them with the closure.

For example here's a counter that doesn't require a variable in global scope:

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())

Doing this with a global count variable is messy and risks some other part of the code clashing with the global variable. Above, nothing other than the c function can access the counter. In fact you can make several independent ones:

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())

There's a lot you can do with closures and they're important in Javascript. It's worth taking the time to really understand them.




回答2:


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

Is the same as writing (without the benefits of "this")

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

It's a function that returns another function that uses the passed parameters. This is called a Curry function

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

Here's a better example

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

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

You can use curried functions very easily with Arrays



来源:https://stackoverflow.com/questions/53860763/what-does-return-local-do-in-this-closure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!