简体   繁体   English

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

[英]Does Javascript Use Dynamic Name Resolution?

This is my go to test for whether a language has dynamic name resolution. 这是我测试一种语言是否具有动态名称解析的方法。

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

If the language uses dynamic name resolution, the code should print 10. Otherwise, it should throw an undefined error. 如果该语言使用动态名称解析,则代码应显示10。否则,应引发未定义的错误。

Javascript prints 10. But Javascript uses variable hoisting, which moves var a to the top foo and invalidates my test. Javascript打印10。但是Javascript使用变量提升,将var a移动到顶部foo并使我的测试无效。

Edit: If we could delete variables in JS, the following would be an excellent test: 编辑:如果我们可以删除JS中的变量,以下将是一个很好的测试:

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

If JS statically resolves names, bar's a references foo's a . 如果JS静态解析名称,则bar a引用foo为a Since foo's a gets deleted (if it were possible), bar would print undefined . 由于foo的a被删除(如果可能的话),bar将显示undefined

If JS dynamically resolves names, bar's a will be looked up dynamically when bar() is called. 如果JS动态地解析名称,则在调用bar()时将动态查找bar的a Since foo's a is already deleted at this point, the lookup would find the global a, and bar would print 5. 由于foo's a已经被删除,查找将找到全局a,bar将显示5。

Does Javascript Use Dynamic Name Resolution? Javascript是否使用动态名称解析?

Yes. 是。 Consider the following example : 考虑以下示例

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

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

The variable foo isn't bound to the lexical environment until runtime (due to the eval() statement), but the fact that no error is thrown (and the code works) demonstrates that the name is resolved dynamically. 变量foo直到运行时才绑定到词法环境(由于eval()语句),但是没有引发错误(并且代码有效)的事实表明,该名称是动态解析的。


But Javascript uses variable hoisting, which moves var a to the top foo and invalidates my test. 但是Javascript使用变量提升,将var a移动到顶部foo并使我的测试无效。

Note: maybe you're just saying that hoisting is getting in the way of the test you're trying to perform? 注意:也许您只是说吊装妨碍了您要执行的测试? If so, please ignore the rest of this answer... 如果是这样,请忽略此答案的其余部分...

This behavior is actually explained by hoisting, rather than invalidated by it. 实际上,此行为是通过吊装来解释 ,而不是通过吊销来消除的。 Ie,

  • As you pointed out, due to hoisting, the variable a gets created (but not assigned to , yet) at the very top of the foo() function. 如您所指出的,由于提升,变量afoo()函数的顶部创建 (但尚未分配给 foo()

  • Next, you have a function declaration. 接下来,您有一个函数声明。 As it happens, function declarations get hoisted to the top of their scope, too. 碰巧的是,函数声明也被提升到其作用域的顶部。

  • Next you assign the value 10 to a . 接下来,您的值赋给10a Note that this happens before you actually invoke bar() . 请注意,这是您实际调用bar() 之前发生的。

  • Finally, you actually invoke bar() , at which point a already has been assigned the value 10 , resulting in 0 being printed out. 最后,您实际上调用了bar() ,此时已经为a分配了值10 ,结果是打印出0

Combining that all together, your foo() function behaves the same as if it had been written as follows: 将所有这些结合在一起,您的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()
}

I happened to provide a fairly thorough explanation of the difference between declarations and assignments / initialization in an answer just last night. 我恰好在昨晚的一个答案中提供了关于声明赋值 / 初始化之间差异的相当详尽的解释。 It explains much of the behavior seen here as well: Declaring vs Initializing a variable? 它也解释了这里看到的许多行为: 声明与初始化变量?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM