Why erroneous "let/const" declarations create inaccessible variables in a REPL? [duplicate] - javascript

This question already has answers here:
Weird (let) variable assignment behavior in node repl - can't assign values
(1 answer)
Chrome console already declared variables throw undefined reference errors for let
(2 answers)
Closed 3 years ago.
While coding in a Node.js REPL, I accidentally declared a new symbol by using the new keyword and since Symbol() is not a constructor, I got an error as shown in this snippet,
let sym = new Symbol("some description");
// TypeError: Symbol is not a constructor
// at new Symbol (<anonymous>)
So I thought that's fine, I'll do it the right way but I got another error.
let sym = Symbol("some description");
// SyntaxError: Identifier 'sym' has already been declared
That was strange to me because I expected that since my declaration caused an error, the variable has not been defined at all but now I see it seemingly is defined. My next guess was that maybe it got an undefined value, so I tried to reach to this variable and see what value it owns.
console.log(sym);
// ReferenceError: sym is not defined
WHAT? So the variable sym is both defined and undefined?
I even tried to use the block scope of an object so that I can check whether the variable does actually exist in the object using the Object.prototype.hasOwnProperty() function but unfortunately, the same problem emerged and the whole object became undefined and inaccessible.
let obj = {
a: 4,
b: new Symbol("some description"),
};
// TypeError
console.log(obj);
// ReferenceError
let obj = {};
// Syntax Error
I found that this issue could go away if I use var declarations, so I assume it has something to do with block scopes that I don't know.
So I have 3 questions with respect to this problem:
Where is the variable sym defined and where is it undefined? Any connection between this case and the idea of "Temporal Dead Zone"?
What value does sym own?
How can I assign a new value to the sym variable?
Is this problem specific to this case or any erroneous let/const declaration will result in the same issue?

Related

Const is not defined in global scope but defined in local?

Why const is not defined in global scope but defined in local?
screenshoot from devTools
{
console.log(b);
const b = 2;
}
VM366:2 Uncaught ReferenceError: Cannot access 'b' before initialization
at <anonymous>:2:17
console.log(a);
const a = 1;
VM382:1 Uncaught ReferenceError: a is not defined
at <anonymous>:1:13
This seems to be related to some "magic" in how REPL input is handled. It's not really a property of how JavaScript normally works.
If you try this in a node.js file, in a <script>, or even in an (0, eval)('...'), you'll get "Cannot access 'a' before initialization" as expected. Note that even in the DevTools console this won't happen if you are in a paused debugger state.
In a non-paused state (only there), the DevTools allow you to declare variables as if you were continuously writing a script, and the declarations will persist across commands. There is clearly "magic" outside of regular JavaScript involved, because even eval would create another temporary scope. That "magic" is handled by V8 itself. It is therefore pretty likely that whatever trickery is used here has the side effect of this slightly unexpected error. (I initially thought the side effect is that the variable declaration isn't hoisted, but if you do a = 0; const a = 1 then you get "Assignment to constant variable", so that doesn't seem to be the case.)
I tried to trace this to the source, but I got lost in the depths of V8. Nonetheless, I discovered (by opening another DevTools to debug the DevTools themselves!) that this only happens if the replMode argument (that gets passed to the V8 backend's evaluate method) is true. This can be verified by setting a breakpoint here and changing the value of options.replMode.
replMode is documented as follows:
Setting this flag to true enables let re-declaration and top-level await.
Note that let variables can only be re-declared if they originate from replMode themselves.
Hoisting workd differently for const and let than var.
SO for const and let, which are block scoped gives ReferenceError error as they do not initialize value as undefined.
-Whereas, for var it will initialize value as undefinded if you do not assign any v alue and var is function scoped. -You can see console from devToolis giving different error, whereasconsolefromstackoverflow``` giving error as our expectation that
"Uncaught ReferenceError: Cannot access 'a' before initialization.
So I believe it's how devtool console treating the error for block-scope and global-scope.
-Check it on ```morzila-devtool`.
{
console.log("before initialization:" + b);
var b = 2;
console.log("after initialization:" + b);
}
console.log("before initialization:" + a);
const a = 1;
This is from Firefox browser
This is from Microsoft Edge
I came to know from this post that, Chrome and IE both have a global event object. So when we are trying to access it first hoisting won't work for const and let. so it's says that we cannot access but window object has access to those variables, So I assume it's throwing error for a is not defined for window object, which is global object.
window object sets automatically to undefind. const window.variable = undefined (when not defined);
Try to run this code:
{console.log(b); var b=1; console.log(window.c); const c=1;}
OUTPUT:
1 debugger eval code:1:9
undefined // window.c = undefined
And as window object has access to global scope it gives error for a or b or variable is not defined when we access it in global scope before initialisation using let or const.

Uncaught ReferenceError: Cannot access 'calculate' before initialization at hesapmakinesi3.html:10 [duplicate]

This question already has answers here:
What is the temporal dead zone?
(3 answers)
Closed 1 year ago.
I take 'Uncaught ReferenceError: Cannot access 'calculate' before initialization at hesapmakinesi3.html:10'
I can't see where error
I don't know any do this
$: strValue =prompt("Please! enter the value ");
$: abc=calculate(strValue);
document.getElementById("demo").innerHTML = abc;
const calculate = s => {
Without seeing much, it looks like you're trying to call a method calculate before it's actually initialized.
You want to first initialize it:
const calculate = s => {};
and then use it after it's being declared.
You're currently trying to use calculate before you've defined it. According to the rules on variable hoisting:
Variables declared with let and const are also hoisted, but unlike for var the variables are not initialized with a default value of undefined. Until the line in which they are initialized is executed, any code that accesses these variables will throw an exception.
So you are seeing that exception.
First define calculate. Then you can use calculate:
const strValue = prompt("Please! enter the value ");
const calculate = s => {
//.. whatever your function definition is
};
const abc = calculate(strValue);
document.getElementById("demo").innerHTML = abc;
(As an aside, I've also added const declarations for your other variables. If they are already declared elsewhere, don't re-declare them here of course. But for completeness of this example I'm simply demonstrating that variables should have declarations so as to not pollute the window object with properties that should have been declared variables.)

Undefined variable with & without object name in JS

When I run the following simple Javascript line...console logs an error.
console.log(abc);
But when I run the above line like
console.log(this.abc); or console.log(window.abc);
the console does not throw an error. Instead it prints "undefined".
Why?
Note: 'abc' variable is not defined or declared.
It's not errornous to refer to a non-existent property, but it is erronous to refer to a standalone variable name which doesn't exist.
When one references a non-existent property on an object, undefined will be returned - that's how how things work. But standalone variable names, on the other hand, do need to be defined before referring to them, in almost all situations. Failing to define a standalone variable before trying to refer to it will throw a ReferenceError in all but 2 situations:
(1) When using typeof
console.log(typeof foo);
(2) When assigning to such a variable in non-strict mode (the variable will be implicitly created on the global object):
const arr = [1, 2, 3];
for (i = 0; i < arr.length; i++) {
// if in sloppy mode, and i hasn't been defined beforehand,
// it will be created as a global variable
}
console.log(typeof i);
If you try to assign to such a variable in strict mode when it hasn't been declared beforehand, an error will be thrown.
When you looking for a variable
console.log(abc);
Is not defined and should throw
Uncaught ReferenceError: abc
is not defined in any context at all
however
console.log(this.abc) and console.log(window.abc)
part of it is defined
console.log(this)
console.log(window)
return current objects instance and window objects respectively and have a reference point. the plain console.log(abc) has no reference point
actually it's not a variable. It is a key which is inside an object. (At this point the object is this or window). this and window created from JavaScript.
It's an interesting question to ask!.
To be able to understand this, we must understand Variable Hoisting in Jaascript.
if you want an undefined for a variable that is not declared yet , well the following would work!
console.log(abc)
var abc = 'ss';
So, here if we try to access a declared variable before it is initialized then undefined is actually assigned at the top of function execution. in other words, all the variables are hoisted to the top of their immediate scope level and are assigned undefined until they reach the initialization point.
to give you a blunt answer, trying to use an undeclared variable would give you Reference Error while trying to access a declared variable before the initialization would give youundefined
and, for objects like this and window well they are available objects . so basically at this point people say, In Javascript everything is present, meaning, trying to access a property that is not yet there in a js object would give you undefined.
On most browsers and Javascript environments that respect Javascript specification (this may change in other javascript environments where there is no console):
Any property that has not been assigned a value or non existent property (or a function without a return statement) returns undefined.
In the first examples, the dot operator is being called. The behaviour in case you access a non existent property is defined and it is that to return undefined, which is a valid js type. Therefore undefined is being logged.
On the last example, on the other hand, the non existent variable throws a ReferenceError. This happens directly, as unlike the first case, no context has been accessed, no dot operator is being called and this is just a plain error.
It is the normal JavaScript behavior.
Lets consider a variable name
var name;
console.log(name);
The above wont throw an error, because the variable name was declared before using it in console.log.
console.log(name);
This will throw a reference error because you did not declare the variable first.
But,
If name is accessed from an already defined variable( e.g. window, this ), it wont throw an error whether defined or not. Just like the below will simply print undefined, reference error wont be thrown.
console.log(window.name);
Note that window is already defined by the browser.
Notwithstanding,
console.log(window_a.name);
the above will throw a reference error because name is being accessed on an undefined variable window_a.
var window_a = {};
console.log(window_a.name);
This wont throw reference error because window_a is now declared.

Why does reference exception does not come in case of undeclared object properties? [duplicate]

This question already has an answer here:
Why does referencing undeclared variables throw a reference exception but referencing undeclared properties doesn't?
(1 answer)
Closed 5 years ago.
In JS, doing a read access on undeclared variable gives reference exception.
I tried following code:
var obj = { };
console.log(obj.v1);
This prints undefined
console.log(v2);
While this throws exception.
What is the reason for different behavior?
I was expecting exception in both cases as both v1 and v2 are undeclared.
EDIT: More confusing is the fact that if v2 was declared in global scope, it would have become property of window object. So does it not become similar to the case that I am accessing an undeclared property of window object? Same as case 1?
var obj = { };
console.log(obj.v1);
obj is defined but it's property v1 doesn't exist, so output undefined.
console.log(v2);
v2 is not declared so, output like Uncaught ReferenceError: ...
for window.v2 output is undefined but for only v2 output is: ReferenceError.
var foo = 1;
// Explicit global/window variable (new variable)
bar = 2;
// Implicit global/window variable (property of default global object)

What is the logic behind when JavaScript throws a ReferenceError?

I've been using JavaScript for years but have been trying to increase my deep, under-the-hood type knowledge of the language lately. I'm a bit confused about what the logic is behind when JavaScript throws a ReferenceError.
For example, none of these throw a referenceError, but still write undefined to the console:
function foobar(foo)
{
var bar = foo;
console.log(bar);
}
foobar();
or
var foo = undefined;
var bar = foo;
console.log(bar);
or
var foo;
var bar = foo;
console.log(bar);
but this obviously does throw a ReferenceError error on the first line without writing to the console:
var bar = foo;
console.log(bar);
So it seems that having a variable in a parameter list or declaring it will stop a referenceError from being thrown - even though the variable is still 'undefined'.
Does anyone know what's going on under the hood or what the hard and fast rules are surrounding this? Does anyone know why these aren't considered referenceErrors?
There's a difference in using a variable that exists but has an undefined value, and using a variable that doesn't exist and was never declared.
The latter will create a reference error as you're trying to reference something that doesn't exists and has not been declared.
On the other hand, when you do
var foo;
foo does exists, and it has been declared, it's value is just undefined, so you can still reference it without throwing an error.
In other words, trying to reference a variable that hasn't been declared will throw a reference error, while referencing declared variables will never throw a reference error, regardless of wether or not a value has been set for that variable.

Categories

Resources