Hoisting leads to (unwanted?) shadowing (Re: Inner functions and outer 'this')

# Claus Reinke (14 years ago)

[about protection keys:]

.. I just don't see the general problem (if it is even a "problem") as one that is important enough to try to "fix" in the language
since it is probably rare and it can be avoided by careful naming.

The problem of variable shadowing happens to be more acute in Javascript than in other languages. The reason for this is the way 'var' initialization interacts with hoisting (exposing implementation- level details such as creating bindings before initializing them).

In a variable initializer, the initial value can not refer to any outer bindings for any names that are bound in the body of the current function scope:

function Outer() { var prefix = "Outer", x = "hi"; function Inner () { var prefix = prefix+">Inner", // "undefined>Inner" greeting = x+" there"; // "undefined there"

    log(prefix);
    log(greeting);

    for(var x = "noone";false;) { }
}
Inner();

} Outer();

Shadowing is the problem, renaming is a workaround, protection keys are one solution (if it helps, think of them as systematic, hence predictable and recognizable renaming).

If the new 'let' bindings work similarly, that problem is going to get worse (more nested scopes) and better (smaller nested scopes). But as long as hoisting prevents access to outer bindings, protection keys would be even nicer to have in Javascript than in other languages.

Without them, I am afraid we're not going to see immediately applied functions retired just yet, because their initial values are unaffected by the scope in which the new name is defined:

(function(x) { ... (function (x) { .. x .. }(x+" there")) .. }("hi"));

In general, arguing in favour of protection keys based on merit is possible, but not likely to convince those who have not yet had experience with them. Protection keys on their own might look like an intellectual curiosity (and it always seems that "just one more renaming" will fix "the issue at hand"), their value comes from enabling other features (mostly related to user-visible program transformations, where renaming or shadowing get in the way).

On that topic, let me just say that I've missed the interactive functional programming features of reduction systems, all enabled by protection keys, ever since I moved into the world of Haskell. I try to spread the basic ideas when I can - the next time you run into a problem they could solve, you will already be familiar with them!-)

Claus