在 Javascript 中,闭包可以与函数 return 值共享作用域吗?

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

我试图从 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"]);

我想我明白内部函数 track 将如何维护对 downkeys 的引用,因为它是一个闭包,但我迷失在 return down;

return 值会是对回调正在访问的 down 完全相同的引用吗?我不明白;我以为局部变量只能被内部函数访问?

跟进:如果 down 是原始数据类型而不是对象,这仍然有效吗?

该函数将变量 down 初始化为一个对象。

所以在函数内部,down是一个指向某个对象的变量

当函数 returns down 时,它 returns 是对象的引用,这意味着对象可以通过函数的 return 访问。

如果 down 是原始值,那么这将不起作用,因为该函数只会 return 原始值而不是对对象的引用。

TLDR: 由于人类语言固有的不精确性,说“一个变量是 returned”是模棱两可的。这并不意味着标识符和值的变量对是 returned。这意味着变量的 value 是 returned。在这种情况下,对对象(由 Object.create(null) 创建)的引用的值是 returned.

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

是的。

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

变量是标识符(即变量的名称)和值的配对。

范围是标识符(在本例中为“down”)具有特定含义的代码区域。

标识符的范围由声明变量的方式决定(const/let/var/在非严格模式下是隐式的)。使用 let 声明变量 down;因此它的作用域是最近的包含块,即函数 trackKeys.

trackKeys 内声明的函数将通过 JavaScript 的内置闭包形成机制关闭 down,因此将共享标识符“向下”的含义。

注意:如果内部函数或块 声明它们自己的名为 "down" 的变量,这些内部变量将导致错误(var 在严格模式下的非功能块,重复声明),什么也不做(var 在非功能块的非严格模式下),或隐藏(从视图中隐藏)外部变量(let/ const).

返回 down 不会更改标识符 down 的范围。尝试在 trackKeys 之外引用“向下”将继续出错或 return 未定义,具体取决于您是否处于严格模式。然而,返回 down 的值确实使该值在 trackKeys.

之外可用