【问题标题】:Does Javascript Use Dynamic Name Resolution?Javascript 是否使用动态名称解析?
【发布时间】:2015-07-30 13:54:26
【问题描述】:

这是我去测试一种语言是否具有动态名称解析。

function foo() {
    function bar() {
        print a
    }
    var a = 10
    bar()
}

如果语言使用动态名称解析,代码应该打印 10。否则,它应该抛出一个未定义的错误。

Javascript 打印 10。但是 Javascript 使用变量提升,它将 var a 移动到顶部 foo 并使我的测试无效。

编辑: 如果我们可以在 JS 中删除变量,那么下面将是一个很好的测试:

var a = 5
function foo() {
    var a = 10
    function bar() {
        print a
    }
    delete a
    bar()
}
foo()

如果 JS 静态解析名称,bar 的 a 引用 foo 的 a。由于 foo 的 a 被删除(如果可能的话),bar 将打印 undefined

如果JS动态解析名字,bar的a会在bar()被调用时动态查找。由于此时 foo 的 a 已被删除,查找将找到全局 a,而 bar 将打印 5。

【问题讨论】:

  • 首先,定义“动态名称解析”的含义
  • This question 关于变量作用域可能是您所追求的,或者可以帮助您重新表述您的问题,以便更清楚地了解您的问题?
  • “但是 Javascript 使用变量提升,它将 var a 移动到顶部 foo 并使我的测试无效。”为什么你觉得这会使你的测试无效?
  • @Alnitak 通过动态名称解析,我的意思是对变量的引用直到运行时才附加到实际变量。相反,静态名称解析意味着编译器可以在不运行代码的情况下找出引用指向的变量。例如,如果 Javascript 使用静态名称解析,编译器可以判断 bar() 引用的是 foo 的 a,而不是其他的 a(如全局 a)。

标签: javascript variables late-binding


【解决方案1】:

Javascript 是否使用动态名称解析?

是的。考虑以下example

eval("var foo = 'foo';");

console.log(foo);
// > "foo"

变量foo 直到运行时才绑定到词法环境(由于eval() 语句),但没有抛出错误(并且代码有效)这一事实表明该名称是动态解析的。


但是 Javascript 使用变量提升,它将 var a 移动到顶部 foo 并使我的测试无效。

注意:也许您只是说吊装妨碍了您尝试执行的测试?如果是这样,请忽略此答案的其余部分...

这种行为实际上是通过提升来解释的,而不是被它无效化。即,

  • 正如您所指出的,由于提升,变量a 在最顶部创建(但尚未分配给foo() 函数。

  • 接下来,您有一个函数声明。碰巧,函数声明也被提升到其作用域的顶部。

  • 接下来将值 10 分配给 a。请注意,这发生在您实际调用bar() 之前。

  • 最后,你实际调用了bar(),此时a已经被赋值为10,导致0被打印出来。

将所有这些结合在一起,您的 foo() 函数的行为与编写如下一样:

function foo() {
    // hoisted
    var a;

    // also hoisted
    function bar() {
        // due to hoisting, `a` is lexically in scope here
        console.log(a);
    }

    // the actual assignment
    a = 10

    // the invocation
    bar()
}

我碰巧在昨晚的回答中对声明赋值/初始化之间的区别进行了相当彻底的解释。它也解释了这里看到的大部分行为:Declaring vs Initializing a variable?

【讨论】:

  • 您似乎在解释测试代码的作用,这不是问题所在。问题是关于名称解析(你甚至承认你不明白它的含义。)
  • @Juhana 很公平,我猜。 FWIW,我试图解释那里看到的行为是如何由于提升,而不是被它无效。
  • 评估测试很好。我们知道 eval 不只是规则的例外吗?
  • @BrettGeorge 我想不出另一种方法来引入另一个动态命名变量(Function(string) 构造函数除外,但这并不能证明任何事情,因为您还必须从相同的函数体)。
猜你喜欢
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-05
  • 2019-02-26
  • 2017-08-01
  • 1970-01-01
相关资源
最近更新 更多