【问题标题】:How is the arrow function(which is an argument), accepting the value of x as 1 and returning it?箭头函数(它是一个参数)如何接受 x 的值作为 1 并返回它?
【发布时间】:2019-07-29 19:39:10
【问题描述】:
console.log((function(x, f = () => x) {
  var x;
  var y = x;
  x = 2;
  return [x, y, f()];
})(1));

这是代码 sn-p。这里的输出是 (3) [2, 1, 1] 第三个输出是 1 而不是 2 怎么样?

另外,如果我在 Scratch JS 上运行此代码,它会打印 (3) [2, 1, 2]

为什么这里的输出不同?

我尝试在 IIFE 函数中传递第二个参数,如下所示:

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

但这会引发错误

chrome 控制台中的输出为 (3) [2, 1, 1],但 Scratch JS 中的输出为 (3) [2, 1, 2]

【问题讨论】:

    标签: javascript console.log arrow-functions iife hoisting


    【解决方案1】:

    第三个输出是 1 而不是 2? [...] 为什么这里的输出不同?

    如果代码按照编写的方式运行,则在进入函数之前评估默认参数。所以f = () => x中的x指的是函数的第一个参数,而不是里面定义的var x。由于 1 被传递给 IIFE,所以 1 是使用的值。 为什么这里的输出不同? 看来,scratchJS 正在转换为旧版本的 javascript。这会将代码变成这样:

     console.log(function (x) {
        var f = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
          return x;
        };
        var x;
        var y = x;
        x = 2;
        return [x, y, f()];
      }(1));
    

    现在默认值由函数体内的代码处理。因为hoistingvar x 是在执行return x 时引用的变量,而不是参数列表中的 x。在调用 f 时,该局部变量已设置为 2,因此记录了 2。

    【讨论】:

    • 您完全正确,先生!我使用 ES2015 预设在 Babel 上编译了 sn-p,并将代码转换为您发送的内容。但是当我把预设转成 ES2017 的时候,代码一点都没变!您的推理解释了不同的输出。谢谢!
    【解决方案2】:

    在第一种情况下,() => x 返回 1,因为您没有将函数作为第二个参数传递,这意味着箭头函数在您的函数之外实例化并保留其自己的上下文。函数内部的x 被限制在不同的上下文中。

    这是一个带有阴影名称变量的经典问题,名称相同但嵌套上下文不同。

    在第二个示例中,您将值 2 作为参数中的函数传递,这就是它抛出的原因。你不能执行2()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-17
      • 2015-04-11
      相关资源
      最近更新 更多