Code Monkey home page Code Monkey logo

Comments (7)

anba avatar anba commented on May 20, 2024

It prints "undefined" in sloppy mode and throws a ReferenceError in strict mode.

Spec sections:

  • Block Declaration Instantiation creates, but does not initialise the lexical binding.
  • In typeof Evaluation, the reference is not unresolvable (because the binding was found), so GetValue is executed. The reference's base value is an environment record, so GetBindingValue gets called. And step 3.a in that method either returns undefined or throws a ReferenceError, depending on the strict mode setting.

from understandinges6.

getify avatar getify commented on May 20, 2024

@anba

It is quite surprising that typeof would behave differently for undeclared variables vs. TDZ let variables:

"use strict";
console.log(typeof a);
console.log(typeof b); // ReferenceError
let b = 2;

Wouldn't it have made more sense for it to behave the same in both cases? What's the justification for the error in the b case but not with a?

from understandinges6.

anba avatar anba commented on May 20, 2024

The typeof result for a is legacy behaviour and cannot be changed, regardless of whether it makes sense or not. And the result for b actually derives from that legacy behaviour. For example you can achieve the same effect without TDZ variables if you use global variables:

let global = this;
Object.setPrototypeOf(global, new Proxy(Object.create(null), {
  _has: false,
  has(t, pk) {
    // Switch the HasBinding() result for the global object environment on every access
    return this._has = !this._has;
  }
}));

typeof a; // undefined
"use strict"; typeof a; // ReferenceError

from understandinges6.

getify avatar getify commented on May 20, 2024

@anba

Thanks for the clarification, but I was actually asking the reverse question. Perhaps I'm missing it, but I'm not sure I understand why there needed to be an error on typeof b while in the TDZ. I would have thought, to preserve consistency with the typeof a case, that typeof b would always return undefined regardless of strict mode. What I'm wondering is if there's some other reason/justification for this error, since it breaks consistency and thus surprises (at least me)?

To put it another way, I see it as a feature, not a bug, that typeof is "safe" to use with variables if you're not sure if they are declared or not. This typeof a !== "undefined" type of check is used many times in real-world code to check if a variable (usually a global) exists or not, where just checking for the variable by name would in fact throw an error if it wasn't declared.

It would seem at quick glance that being able to do similar checks in a safe way against TDZ'd let declarations could be similarly useful.

from understandinges6.

nzakas avatar nzakas commented on May 20, 2024

Thanks @anba for the explanation. Seems like some good fodder for es-discuss.

from understandinges6.

anba avatar anba commented on May 20, 2024

The typeof operator applied on the (internal) Reference type only differentiates between unresolvable and resolvable references, cf. step 2 in typeof - Runtime Semantics: Evaluation. For typeof a the unresolvable reference case applies, whereas in typeof b the reference to b was successfully resolved and its value is retrieved. The same behaviour is specified in ECMAScript 5. That's what I mean when I speak of legacy behaviour.
(Even for ES5 the ReferenceError in strict mode is specified, except that user code can never actually create references to uninitialised bindings in ES5...!)
That being said, it is certainly possible to extend ES6 to catch the resolved but not yet initialised case and make it return undefined.

from understandinges6.

getify avatar getify commented on May 20, 2024

Dunno what if anything will come of it, but I filed this as a ES6 bug: https://bugs.ecmascript.org/show_bug.cgi?id=3009

from understandinges6.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.