RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 751965
Accepted
smellyshovel
smellyshovel
Asked:2020-12-01 00:55:23 +0000 UTC2020-12-01 00:55:23 +0000 UTC 2020-12-01 00:55:23 +0000 UTC

为什么覆盖参数时 var 的存在会影响对返回该参数的函数的调用?

  • 772

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

似乎是最简单的代码,从逻辑上讲,它应该返回2。但它返回1。

我相信如果将这种行为f声明为:

  1. IIFE型f = (() => x)()
  2. 简单的视图分配f = x

在这些情况下,该值f将被计算一次并且已经是常数(很明显,那时f不可能将其作为函数调用,但现在不是这样)。

但是,由于f是一个我认为应该根据 的值以不同方式执行的函数,x所以代码的行为对我来说并不清楚。

我想当被调用时,该函数f将返回 value x,此时它已经等于2(被上面的行覆盖)。但该函数仍然返回1。为什么?


经过反复试验,发现如果f在函数体中重写,

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

然后代码开始按我的预期工作。由此我得出结论,这里的决定性因素是定义函数的位置(即,它被定义为参数的默认值)。但是,再一次,为什么这很重要?


在写这个问题时,我更进一步,还发现x. 如果代码看起来像这样(没有关键字var),

(function(x, f = () => x) {
  x = 2;
  console.log(f());
})(1)

那么结论又是合乎逻辑的 - 2。

同时,我假设的第一件事是,由于函数是在参数字符串中定义的(作为默认值),所以它的值x不是作为函数体x中变量的值,而是作为值。但是无论是在场还是在场,价值本身都不会改变。这是函数执行的结果——是的。所以这是另一回事。唯一的问题是什么?argument[0]vararguments[0]

javascript
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    smellyshovel
    2020-02-24T23:39:10Z2020-02-24T23:39:10Z

    为什么第一个示例的输出1而不是输出的问题的答案2在于函数的形式参数。

    规范的当前修订版(版本)在第9.2.12 节 FunctionDeclarationInstantiation中描述了函数的执行(更准确地说,初始化)。它还以纯文本形式表示,在函数初始化期间词法环境及其条目发生的情况取决于形式参数:

    当为评估 ECMAScript 函数建立执行上下文时,会创建一个新的函数环境记录,并在该环境记录中实例化每个形式参数的绑定。函数体中的每个声明也被实例化。如果函数的形式参数不包含任何默认值初始化器,则主体声明将在与参数相同的环境记录中实例化。如果存在默认值参数初始值设定项,则为主体声明创建第二个环境记录。形式参数和函数被初始化为 FunctionDeclarationInstantiation 的一部分。所有其他绑定在函数体的评估过程中被初始化。

    特别是,如果函数的形参中至少有一个参数定义了默认值(简称为“默认参数”),则为函数体内的所有声明创建一个单独的词法环境。

    正是出于这个原因,表达式在专门创建的词法环境中var x = 2定义了一个新变量。

    但是,由于函数定义f引用了另一个 Lexical Environment(为形参创建的那个),所以当它被调用时,将取变量的值,x记录在其中的 Lexical Environment 的记录中该功能已定义f。简单地说,1.

    此外,规范将其定位为“功能”。在算法 9.2.12 的步骤27.a中,她说为函数体内的声明创建了一个单独的词法环境,以便形式参数之间的闭包无法访问函数体内声明的变量:

    注意:需要一个单独的环境记录来确保由形式参数列表中的表达式创建的闭包不具有函数体中声明的可见性。

    这正是问题中给出的示例中发生的情况。正是从这一点来看,规范试图保护我们(尽管这种“关心”的好处颇有争议,但现在不是这样了)。

    当函数的形参中没有一个默认参数时,情况完全相反:

    (function(x) {
        var x = 2;
        var f = () => x;
        console.log(f());
    })(1);

    在这种情况下,函数体中的声明和形参之间的声明都指向同一个词法环境。因此,表达式var x = 2准确地重新定义了存在于同一范围内的变量x。

    但是,如果x函数体内的变量是使用关键字声明的let,那么在这种情况下,我们会得到一个语法错误:

    (function(x) {
        let x = 2;
        var f = () => x;
        console.log(f());
    })(1);

    这是由于关键字的机制let,特别是不允许重复声明这样的变量。

    实际上,这是一个简化的解释。在某些情况下,即使使用关键字let(即使形式参数中没有默认参数),仍然会为此类声明创建一个新的词法环境。附录 B.3.3.1 中有关此内容的更多信息。但是,在这个答案的范围内,这些功能并不是特别有趣,所以我将省略它们。


    最后一件事,关于问题的最后一个例子:

    (function(x, f = () => x) {
        x = 2;
        console.log(f());
    })(1)

    在这种情况下,答案2是由于缺少关键字var。

    由于x这里的变量不是在新的词法环境中声明的(为什么是新的,上面读过),而是覆盖了x在父词法环境中声明的变量(顺便说一下,对创建的词法环境的外部词法环境的引用)函数体内的声明准确地指向在创建“附加”词法环境之前就存在的词法环境,参见第 27.b) 条,函数调用f将返回已经重新定义的变量值x。

    • 3

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5