Live data from Hacker News

The Temporal Dead Zone, or why the TypeScript codebase is full of var statements

vincentrolfs.dev

61–64 of 64 posts

Re: The Temporal Dead Zone, or why the TypeScript codebase is full of var statements

#61
post #2

The first example is not “terrible”, that’s just how lexical scope works. I don’t really see the point of complaining about language features like this - either learn how it works or ignore at your peril.

I second that, I actually don't understand why do people believe every pair of curly braces has to be its own separate scope. An explicit construct for scoping would have been so much clearer to me.

> An explicit construct for scoping would have been so much clearer to me.

Yes, maybe we could use something similar to parenthesis. Maybe they can look curly. /s

Re: The Temporal Dead Zone, or why the TypeScript codebase is full of var statements

#62

I've tried to get V8 at least to implement smarter TDZ elision for a long time, which would eliminate the need for these shenanigans. There are some relatively simple heuristics where you can tell without escape analysis that a variable will not be referenced before initialization. The obviously bad constructions are references in the same scope that happen before the declaration. It'd be nice if these were an early…

This kind of elision is implemented.

Re: The Temporal Dead Zone, or why the TypeScript codebase is full of var statements

#63
post #52
post #11

Earlier quoted context omitted.

That's not how lexical scope works anywhere but in JavaScript. Or rather, it's the interaction between "normal" lexical scope and hoisting. In a "normal" lexically scoped language, if you tried: function f() { return x; // Syntax parsing fails here. } let x = 4; return f(); you would get the equivalent of a ReferenceError for x when f() tried to use it (well, refer to it) at the commented line. But in JavaScript, thi…

Would mutual recursion still work with this solution? E.g. function f() { return g() } function g() { return f() }

Yes, because those don't capture any lexicals, so they're hoisted as usual.

My solution would only stop hoisting closures that capture lexicals, with the idea that capturing a lexical means that the closure's identity is now tied to that lexical environment anyway so it's kind of bizarre to hoist it out to where part of its identity is missing.

But you were giving a simplified example, so I want to be sure I'm not dismissing your concern unfairly. This would not work:

    function f() {
        return g(); // ReferenceError
    }
    let x = 4;
    function g() {
        return x + f();
    }
Hm... you raise a good point, though. Should this work?:

    let x = 4;
    function f() {
        return x + g(); // ReferenceError? Unfortunate if so...
    }
    function g() {
        return x - f();
    }
perhaps the proposal needs to be modified: instead of not hoisting lexical closures (functions that close over lexicals) at all, hoist them to the nearest lexical scope containing everything they close over. So the above would work, but this would still be an error:

    let x = f(); // ReferenceError
    let y = 2;
    function f() {
        return y;
    }
Not that I'm proposing anything at all, this is all wishful thinking. Though I've wondered if there could be a way to opt-in to this somehow, something like:

    let x = 4;
    let function f() {
        return x + g();
    }
    let function g() {
        return x - f();
    }
(or `const function`, I suppose, but I don't know if there's a useful distinction.) Then these lexical functions would never need to consider the case where they capture uninitialized bindings. But that's kind of weird, in that `let f = () => { ... };` looks similar to `let function f() { ... }` but the former would still have to hoist. Bleagh. Oh well.

Re: The Temporal Dead Zone, or why the TypeScript codebase is full of var statements

#64

Earlier quoted context omitted.

The interesting part here is that javascript interpreters not having to track the TDZ comes with an interesting performance bonus.

javascript interpreter* They are only talking about one javascript engine (node). They didn't test any other engine or go into the implementation in node. For all we know, this might just be a poorly optimized code path in node that needs a little love, but the author didn't bother doing any investigation. Looking at the linked github issue, jsc doesn't have the performance penalty. It would have been interesting if…

> If this article is about hoisting then this is a well-made high-effort high-value article.

? There is no mention of hoisting in the article, not the name or the concept. I am not even sure the author knows the concept of hoisting and that 'let' and 'var' behave differently. All the examples are suspiciously missing the key differences, and all the surrounding text is about the scope of the if construct.

Post reply on HN