I have a question about JavaScript. When I declarate new variable and assign to it new instance of class, if error is thrown variable is getting completely unusable.
Code below should throw an error
class MyClass {
constructor (config) {
this.someProperty = config.someProperty || '';
}
}
let myClassInstance = new MyClass();
If I try to assign something to it, JavaScript will throw an error.
myClassInstance = '123'
Uncaught ReferenceError: myClassInstance is not defined
Then I tried to define variable
let myClassInstance = '123'
Uncaught SyntaxError: Identifier 'myClassInstance' has already been declared
Variable also cannot be deleted. Is there anything that we can do with that issue? I'm just curious, of course I will handle passing undefined as config to constructor.
EDIT: I also tried using var, I can then reuse myClassInstance. I wonder why if I use let that variable cannot be deleted, declarated or new value cannot be reassigned.
EDIT 2: I can handle passing undefined or pass empty object. Just pure curiosity what happens in JS console with that variable, also code will not execute if you paste everything at once
I have a question about JavaScript. When I declarate new variable and assign to it new instance of class, if error is thrown variable is getting completely unusable.
Code below should throw an error
class MyClass {
constructor (config) {
this.someProperty = config.someProperty || '';
}
}
let myClassInstance = new MyClass();
If I try to assign something to it, JavaScript will throw an error.
myClassInstance = '123'
Uncaught ReferenceError: myClassInstance is not defined
Then I tried to define variable
let myClassInstance = '123'
Uncaught SyntaxError: Identifier 'myClassInstance' has already been declared
Variable also cannot be deleted. Is there anything that we can do with that issue? I'm just curious, of course I will handle passing undefined as config to constructor.
EDIT: I also tried using var, I can then reuse myClassInstance. I wonder why if I use let that variable cannot be deleted, declarated or new value cannot be reassigned.
EDIT 2: I can handle passing undefined or pass empty object. Just pure curiosity what happens in JS console with that variable, also code will not execute if you paste everything at once
Share Improve this question edited Mar 15, 2017 at 18:39 JLRishe 102k19 gold badges137 silver badges171 bronze badges asked Mar 15, 2017 at 12:23 Alan MroczekAlan Mroczek 1,1991 gold badge12 silver badges27 bronze badges 10- 1 Try using var instead of let. – clu3Less Commented Mar 15, 2017 at 12:29
- not helping, I tried – Alan Mroczek Commented Mar 15, 2017 at 12:30
- Show us some more code. I am pretty sure, the issue must be of scoping – Kiran Shinde Commented Mar 15, 2017 at 12:31
- However if I assign new instance of class using var, then I can reuse that variable, I wonder what happens with let – Alan Mroczek Commented Mar 15, 2017 at 12:32
- @Kenny just paste code to chrome debug or something similar, and then you can see what I mean – Alan Mroczek Commented Mar 15, 2017 at 12:34
2 Answers
Reset to default 18Running code in the interactive console creates a contrived situation that couldn't happen in typical code execution.
Firstly, what you're seeing isn't specific to errors thrown in class constructors. You can observe the same behavior if you execute any let
statement where the RHS throws an error:
let myVariable = "".boom();
The documentation on MDN talks about a "temporal deadzone" where a variable declared with let
exists, but is treated as not existing until the let
statement has successfully executed.
From the ES6 spec:
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.
In simple terms, the variable has been created, but cannot be accessed because its "LexicalBinding" has not been evaluated.
Using the console, you have created a situation where:
- The
let
statement has not successfully executed (so it is aReferenceError
to try to access its variable). - You have two
let
s for the same variable name within the same scope (so the second one creates a syntax error). (n.b. Simply having twolet
s in the same scope would cause the code to fail at the compilation stage, before the first one even had a chance to try to execute if you weren't entering the code a little bit at a time into the console).
This is a situation that could not occur in ordinary code.
Ordinarily, you would not be able to continue running statements in the scope where an error has been thrown, so the first bullet would be impossible. The console allows you to do that.
It would be further impossible under ordinary circumstances because the code would fail at the compilation stage, before the first let
statement could even try to run.
So that's why you're getting an error in both cases.
Okay, this question is actually really interesting and I may have found an answer for it.
The phenomenon you are describing is most likely related to how the Javascript engine compiles your code. While it may seem otherwise to the programmer, the compilation consists of several steps and are executed at different stages during the process. So, depending on what kind of error you have in your code, this process can terminate at any point of the process.
So, if your object creation is flawed (config
is undefined) but the syntax per se is fine (from a language standpoint) you'll get an error later on in the compilation process compared to something that is illegal in Javascript generally.
See, let
is quite sophisticated because it prevents variable naming collisions (hence the Indentifier 'myClassInstance' has already been defined
error). This is unlike var
which does not have this feature.
From the MDN documentation:
Redeclaring the same variable within the same function or block scope raises a SyntaxError.
if (x) { let foo; let foo; // SyntaxError thrown. }
In ECMAScript 2015, let will hoist the variable to the top of the block. However, referencing the variable in the block before the variable declaration results in a ReferenceError. The variable is in a "temporal dead zone" from the start of the block until the declaration is processed.
TL;DR
The following code will trigger an error earlier on during the compilation process
let myClassInstance = new MyClass();
let myClassInstance = '123';
compared to:
let myClassInstance = new MyClass();
myClassInstance = '123';
This is because the former is illegal syntax in Javascript, whereas the latter isn't. In the latter case the code will compile fine, but will fail in runtime because the argument is undefined.
EDIT:
I found this blog and is quite an interesting read. Snippet:
Huh? In simple terms, this JavaScript engine takes your source code, breaks it up into strings (a.k.a. lexes it), takes those strings and converts them into bytecode that a compiler can understand, and then executes it.
Another deep-dive tutorial here.