Home > Blockchain >  In Javascript, can a closure share scope with a function return value?
In Javascript, can a closure share scope with a function return value?

Time:12-26

I'm trying to understand this unexplained code from Eloquent Javascript :

function trackKeys(keys) {
  let down = Object.create(null);
  function track(event) {
    if (keys.includes(event.key)) {
      down[event.key] = event.type == "keydown";
      event.preventDefault();
    }
  }
  window.addEventListener("keydown", track);
  window.addEventListener("keyup", track);
  return down;
}

var arrowKeys =
  trackKeys(["ArrowLeft", "ArrowRight", "ArrowUp"]);

I think I understand how the inner function track will maintain a reference to down and keys because it is a closure, but I'm lost at return down;

Will that return value be a reference to the exact same down the callbacks are accessing? I don't understand; I thought local variables could only be accessed by inner functions?

Follow-up: what if down were a primitive data type and not an object, would this still work?

Thanks!

CodePudding user response:

The function initializes the variable down as an object.

So within the function, down is a variable that points to a certain object.

When the function returns down, it returns a reference to the object, meaning that the object becomes accessible through the return of the function.

If down were primitive, then this would not work since the function would only return a primitive value rather than a reference to an object.

CodePudding user response:

TLDR: Saying "a variable is returned" is ambiguous due to the inherent imprecision of human language. It does not mean that the variable-pairing of identifier and value is returned. It means the value of the variable is returned. In this case the value of the reference to the object (created by Object.create(null)) is returned.

Will that return value be a reference to the exact same down the callbacks are accessing?

Yes.

I thought local variables could only be accessed by inner functions?

A variable is a pairing of an identifier (ie. the name of the variable) and a value.

Scope is the region of code over which an identifier (in this case "down") has a specific meaning.

The scope of an identifier is determined by the way in which the variable is declared (const/let/var/implicit in non-strict mode). Variable down is declared using let; its scope is therefore the nearest containing block, which is the function trackKeys.

Functions declared inside trackKeys will close over down via the built-in closure-forming mechanism of JavaScript, and will therefore share the meaning of the identifier "down".

Note: if inner functions or blocks also declare their own variable named "down" these inner variables will either result in an error (var in a non-function block in strict mode, duplicate declaration), do nothing (var in non-strict mode in a non-function block), or shadow (hide from view) the outer variable (let/const).

Returning down does not change the scope of the identifier down. Trying to refer to "down" outside trackKeys will continue to error or return undefined depending on whether you are in strict mode. Returning the value of down does, however, make this value available outside trackKeys.

  • Related