1

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.

Javascript prints 10. But Javascript uses variable hoisting, which moves var a to the top foo and invalidates my test.

Edit: If we could delete variables in JS, the following would be an excellent test:

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. Since foo's a gets deleted (if it were possible), bar would print undefined.

If JS dynamically resolves names, bar's a will be looked up dynamically when bar() is called. Since foo's a is already deleted at this point, the lookup would find the global a, and bar would print 5.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Brett George
  • 141
  • 2
  • 7
  • first, define what you mean by "dynamic name resolution" – Alnitak Jul 30 '15 at 14:09
  • [This question](http://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript) about variable scoping may be what you're after, or may help you to rephrase your question so it's a bit clearer exactly what you're asking about? – James Thorpe Jul 30 '15 at 14:10
  • "But Javascript uses variable hoisting, which moves var a to the top foo and invalidates my test." Why do you feel that invalidates your test? – jmar777 Jul 30 '15 at 14:11
  • @Alnitak By dynamic name resolution, I mean a reference to a variable isn't attached to the actual variable until runtime. Conversely, static name resolution means a compiler can figure out which variable a reference points to without running the code. For example, if Javascript used static name resolution, a compiler could tell that bar() was referencing foo's a, rather than some other a (like a global a). – Brett George Jul 30 '15 at 19:51

1 Answers1

4

Does Javascript Use Dynamic Name Resolution?

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.


But Javascript uses variable hoisting, which moves var a to the top foo and invalidates my test.

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. I.e.,

  • 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.

  • 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. Note that this happens before you actually invoke bar().

  • Finally, you actually invoke bar(), at which point a already has been assigned the value 10, resulting in 0 being printed out.

Combining that all together, your foo() function behaves the same as if it had been written as follows:

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?

Community
  • 1
  • 1
jmar777
  • 38,796
  • 11
  • 66
  • 64
  • You seem to be explaining what the test code does, which is not the question. The question is about name resolution (which you even admit that you don't understand what it means.) – JJJ Jul 30 '15 at 14:13
  • @Juhana Fair enough, I guess. FWIW, I was attempting to explain how the behavior seen there is *due to hoisting*, rather than invalidated by it. – jmar777 Jul 30 '15 at 14:18
  • Good call on the eval test. Do we know that eval isn't just an exception to the rule? – Brett George Jul 30 '15 at 19:52
  • @BrettGeorge I can't think of another way to introduce another dynamically named variable (other than the `Function(string)` constructor, but that doesn't prove anything because then you also have to access the variable from the same function body). – jmar777 Jul 30 '15 at 20:03