javascript - 在 IIFE 中两次声明一个变量

标签 javascript iife

我通过互联网上的这个有趣的测验。

console.log((function(x, f = (() => x)){
  var x;
  var y = x;
  x = 2;
  return [x, y, f()]
})(1))

选择是:
  • [2,1,1]
  • [2, 未定义, 1]
  • [2, 1, 2]
  • [2, 未定义, 2]

  • 我选择了解决方案 2 TBH,基于 x 已被重新定义,y 被声明并定义为没有值,并且 f 具有不同的范围,因此获得全局 x 内存点而不是函数 x 内存点。

    但是,我在 jsbin.com 中尝试过

    我发现它是解决方案 1,虽然我不确定为什么会发生这种情况,但我弄乱了函数体并删除了 var x从函数体中,我发现响应更改为 #3,这在 x 值更改时是有意义的,因此它显示 x 和 f 为 2 和 y 为 1,这是全局声明的。

    但我仍然不明白为什么它显示 1 而不是未定义。

    最佳答案

    but still I can't get why it shows 1 instead of undefined.



    不只是你。这是规范的一个深刻而黑暗的部分。 :-)

    这里的关键是有两个x s。对真的。有参数x , 还有变量 x .

    包含表达式的参数列表(如 f 的默认值)有自己的范围,与函数体的范围分开。但在参数列表可能有表达式之前,有 var x在具有 x 的函数中参数无效(x 仍然是参数,具有参数的值)。因此,为了保留这一点,当其中有一个带有表达式的参数列表时,会创建一个单独的变量,并且参数的值为 复制 到函数体开头的变量。这就是这种看似奇怪(不,不仅仅是看似)奇怪行为的原因。 (如果你是那种喜欢深入研究规范的人,这个复制是 FunctionDeclarationInstantiation 的第 28 步。)

    由于f的默认值,() => x ,在参数列表范围内创建,它引用参数x ,而不是变量。

    所以第一个解决方案,[2, 1, 1]是正确的,因为:
  • 2分配给 var x在函数体内。所以在函数的最后,var x2 .
  • 1分配给 y来自变量 x之前 x得到值 2 ,所以在函数的最后,y1 .
  • 参数x的值从未改变,所以 f()结果 1在函数的末尾

  • 就好像代码是这样编写的(我删除了不必要的括号并添加了缺少的分号):

    console.log(function(param_x, f = () => param_x) {
      var var_x = param_x;
      var y = var_x;
      var_x = 2;
      return [var_x, y, f()];
    }(1));


    ...I removed var x from the function body, I found that the response changed to #3...



    #3 是 [2, 1, 2] .这是正确的,因为当您删除 var x从函数来看,只有一个x , 参数(由参数列表中的函数体继承)。所以分配 2x更改参数的值,f返回。

    param_x 为例和 var_x ,如果您删除 var x;,这就是它的样子从中:

    console.log(function(param_x, f = () => param_x) {
      var y = param_x;
      param_x = 2;
      return [param_x, y, f()];
    }(1));



    这是原始代码的注释描述(删除了多余的括号并添加了缺少的分号):
    //                   /---- the parameter "x"
    //                   v  vvvvvvvvvvv--- the parameter "f" with a default value
    console.log(function(x, f = () => x) {
      var x;      // <=== the *variable* x, which gets its initial value from the
                  //      parameter x
      var y = x;  // <=== sets y to 1 (x's current value)
      x = 2;      // <=== changes the *variable* x's value to 2
      //      +---------- 2, because this is the *variable* x
      //      |  +------- 1, because this is the variable y
      //      |  |   +--- 1, because f is () => x, but that x is the *parameter* x,
      //      |  |   |       whose value is still 1
      //      v  v  vvv
      return [x, y, f()];
    }(1));
    

    关于您的标题的最后说明:

    declaring a variable twice in IIFE



    变量只声明一次。另一件事是参数,而不是变量。区别很少重要......这是罕见的时刻之一。 :-)

    关于javascript - 在 IIFE 中两次声明一个变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55560027/

    相关文章:

    iife - 汇总 : globals & external

    javascript - bundle 中包含一个 IIFE 模块

    javascript - 谁能解释一下这段基于 IIFE(立即调用的函数表达式)概念的代码的输出

    javascript - 获取远程 jpg 图像的左上角像素颜色

    javascript - 将 MySQL 的两行放入 PHP 数组中

    javascript - Chrome 中的 HTML5 Canvas 文本抗锯齿,而不是 Firefox

    JavaScript - nubie、window.onload 和 IIFE

    javascript - 使用 d3 force layout 在 svg rect 中添加节点

    javascript - 使用 AngularJS 读取 json

    javascript - 箭头函数(它是一个参数)如何接受 x 的值作为 1 并返回它?