See this code:
<script>
let {foo} = null; // TypeError
</script>
<script>
// Here I want to assign some some value to foo
</script>
The first script attempts to let-declare foo
via a destructuring assignment. However, null
can't be destructured, so the assignment throws a TypeError.
The problem is that then the foo
variable is declared but uninitialized, so if in the 2nd script I attempt to reference foo
, it throws:
foo = 123; // ReferenceError: can't access lexical declaration `foo' before initialization
And let
variables can't be redeclared:
let foo = 123; // SyntaxError: redeclaration of let foo
Is there any way to take it out of the TDZ, so that I can assign values and read them?
The let and const variables are not accessible before they are initialized with some value, and the phase between the starting of the execution of block in which the let or const variable is declared till that variable is being initialized is called Temporal Dead Zone for the variable.
Temporal Dead Zone is the period of time during which the let and const declarations cannot be accessed. Temporal Dead Zone starts when the code execution enters the block which contains the let or const declaration and continues until the declaration has executed.
A temporal dead zone (TDZ) is the area of a block where a variable is inaccessible until the moment the computer completely initializes it with a value. A block is a pair of braces ( {...} ) used to group multiple statements. Initialization occurs when you assign an initial value to a variable.
let and const hoistingVariables declared with let and const are also hoisted but, unlike var , are not initialized with a default value. An exception will be thrown if a variable declared with let or const is read before it is initialized.
It's impossible. Temporal dead zone and restricted access to uninitialized let
variable are expected to be unavoidaible. It's confusing and problematic, but intended and expected.
See spec for details:
NOTE let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer’s AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created. If a LexicalBinding in a let declaration does not have an Initializer the variable is assigned the value undefined when the LexicalBinding is evaluated.\
So if variable wasn't initialized on declaration (and throwing before initialization obviously result in no initialization) it can't be accessed by any means.
But in fact, your issue is more complex than throwing assigment. It's architecture issue - you are depending on mutable global variables. It's big "no no no" and you should refactor your code to use explicit dependencies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With