“Lookup” Is (Mostly) Conceptual
In Figure 2, notice the color of the students
variable reference in the for
-loop. How exactly did we determine that it’s a RED(1) marble?
In Chapter 2, we described the runtime access of a variable as a “lookup,” where the Engine has to start by asking the current scope’s Scope Manager if it knows about an identifier/variable, and proceeding upward/outward back through the chain of nested scopes (toward the global scope) until found, if ever. The lookup stops as soon as the first matching named declaration in a scope bucket is found.
The lookup process thus determined that students
is a RED(1) marble, because we had not yet found a matching variable name as we traversed the scope chain, until we arrived at the final RED(1) global scope.
Similarly, studentID
in the if
-statement is determined to be a BLUE(2) marble.
This suggestion of a runtime lookup process works well for conceptual understanding, but it’s not actually how things usually work in practice.
The color of a marble’s bucket (aka, meta information of what scope a variable originates from) is usually determined during the initial compilation processing. Because lexical scope is pretty much finalized at that point, a marble’s color will not change based on anything that can happen later during runtime.
Since the marble’s color is known from compilation, and it’s immutable, this information would likely be stored with (or at least accessible from) each variable’s entry in the AST; that information is then used explicitly by the executable instructions that constitute the program’s runtime.
In other words, Engine (from Chapter 2) doesn’t need to lookup through a bunch of scopes to figure out which scope bucket a variable comes from. That information is already known! Avoiding the need for a runtime lookup is a key optimization benefit of lexical scope. The runtime operates more performantly without spending time on all these lookups.
But I said “…usually determined…” just a moment ago, with respect to figuring out a marble’s color during compilation. So in what case would it ever not be known during compilation?
Consider a reference to a variable that isn’t declared in any lexically available scopes in the current file—see Get Started, Chapter 1, which asserts that each file is its own separate program from the perspective of JS compilation. If no declaration is found, that’s not necessarily an error. Another file (program) in the runtime may indeed declare that variable in the shared global scope.
So the ultimate determination of whether the variable was ever appropriately declared in some accessible bucket may need to be deferred to the runtime.
Any reference to a variable that’s initially undeclared is left as an uncolored marble during that file’s compilation; this color cannot be determined until other relevant file(s) have been compiled and the application runtime commences. That deferred lookup will eventually resolve the color to whichever scope the variable is found in (likely the global scope).
However, this lookup would only be needed once per variable at most, since nothing else during runtime could later change that marble’s color.
The “Lookup Failures” section in Chapter 2 covers what happens if a marble is ultimately still uncolored at the moment its reference is runtime executed.