Difference between let and var in JavaScript [duplicate] - javascript

This question already has answers here:
What is the difference between "let" and "var"?
(39 answers)
Closed 6 years ago.
I was going through the javascript style guide by Airbnb (https://github.com/airbnb/javascript).
In section 2.2 it is explained that
let is block-scoped rather than function-scoped like var.
// bad
var count = 1;
if (true) {
count += 1;
}
// good, use the let.
let count = 1;
if (true) {
count += 1;
}
I didn't get why the first one is bad practise and second is bad and if both let and var are block scoped then what difference does it make, if I use either of them?
Also what is the difference between function scoped and block scoped?

When something is block scoped it means that you can control the lifetime better and more intutive ways
for example
function a() {
if (true) {
var a = 7;
let b = 42;
}
}
The var a is pulled out in the scope of the function, rather than stying isolated in the block for the if, so like this;
function a() {
var a; // The JS compiler pulls the var out to this level
if (true) {
a = 7;
let b = 42; // but keeps the let in this block.
}
}
.. and that is counter intuitive and sometimes lead to problems -- the let does not have that problem.

Related

var single binding v/s let multiple bindings [duplicate]

This question already has answers here:
Explanation of `let` and block scoping with for loops
(5 answers)
Closed 2 years ago.
In the example below, I have heard that var creates single binding for the variable, while let creates a new binding for each iteration. I wanted to understand in-depth what exactly does it mean and how it works internally?
//var
const arr = [];
for (var i=0; i<3; i++) {
arr.push(function(){
return i;
})
}
console.log(arr.map(function(x){
return x();
}));
//let
const arr = [];
for (let i=0; i<3; i++) {
arr.push(function(){
return i;
})
}
console.log(arr.map(function(x){
return x();
}))
One of the key difference between let and var is:
Variables declared with var or created by function declarations in non-strict mode do not have block scope. Variables introduced within a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope.
Explanation:
I will try to explain in simple words:
"Blocks are scoped to containing function or script" or block statements do not introduce a scope, means anything like below (which is a "block"):
{
StatementList
}
doesn't create its own scope (Block can be created by simply wrapping statements into curly braces).
Okay, lets see an example:
function foo()
{
var x = 1;
{
var x = 2;
}
console.log(x);
}
prints 2.
Function foo has its own scope, but block doesn't. Hence the value changed or new declaration inside block statement(the curly braces outside of line var x = 2 creates new block) is persisted outside the block, i.e. in console statement.
However if we declare a variable x again outside the function foo it will be entirely different and will have its own scope.
suppose we have another function in same script block (or same module/file):
function xyz()
{
var x = 3;
console.log(x);
}
prints 3
What does this mean?, "It means functions create their own scope". So both x one inside foo and other inside xyz are entirely different. Changing one would have effect only inside its own function scope.
Now let
What var is for two different functions, let is for two different blocks. So every block creates its own scope for let.
So if I changed my function foo to:
function foo()
{
let x = 1;
{
let x = 2;
}
console.log(x);
}
prints 1
This means the block inside function has its own scope, and the var x is entirely different from the one outside.
What happens with loop?
It creates different block for each iteration, so loop can be expanded like below:
/*---------Block 1------------*/
{
let i = 0;
//... other loop statments
arr.push(function(){
return i;
});
}
/*----------Block 2-----------*/
{
let i = 1;
//...
arr.push(function(){
return i;
})
}
/*--------- Block 3------------*/
{
let i = 2;
//...
arr.push(function(){
return i;
})
}
Now we see, all three let are having their own scope which is introduced by the pair of curly braces we have for each iteration of loop, but in case of var it will be single scope irrespective of how many blocks we create.
As variable i is not immediately used in block but its used inside a function which creates its own scope and will take the value from its outer scope, in case of var outer scope is only one (which would have final value of i i.e. 3) but in case let there are 3 outer scope, hence each will have its own value.
Reference
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block
For the other differences between var and let:
https://stackoverflow.com/a/11444416/1421196

How can I find out if an ES6 value is var / const / let after it is declared? [duplicate]

This question already has answers here:
How to check that ES6 "variable" is constant?
(4 answers)
Closed 3 years ago.
I know I can find out if a value is var const or let by looking at where it is declared. However I am wondering - mainly for debugging, developing JS compilers, and academic interest - if it is possible to find out the immutability / scope of a variable (var / const / let-ness) after it has been created.
ie
doThing(something)
Would return
let
Or equivalent. Like we can determine types with typeof or something.constructor.name for constructors.
You can distinguish let and const from var with direct eval in the same function as the variable:
let a;
try {
eval('var a');
// it was undeclared or declared using var
} catch (error) {
// it was let/const
}
As #JonasWilms had written earlier, you can distinguish let from const by attempting assignment:
{
let x = 5;
const original = x;
let isConst = false;
try {
x = 'anything';
x = original;
} catch (err) {
isConst = true;
}
console.log(isConst ? 'const x' : 'let x');
}
{
const x = 5;
const original = x;
let isConst = false;
try {
x = 'anything';
x = original;
} catch (err) {
isConst = true;
}
console.log(isConst ? 'const x' : 'let x');
}
let and var are only about the scope, so it's not possible. Because JavaScript does not pass by reference, if you were to pass a variable to a function you would lose the " constness" and also the scope - on that function the variable would just be a locally scoped one. So my thoughts are: it's not possible.
You can't directly access the environment record chain in any way, and therefore you can't tell were a variable was declared. The with statement might enable you to narrow down the scope were a variable was declared as it allows you to add a Proxy as an environment record, but that only gives some insight and it is generally a very dangerous thing to do.
I used to do this but its a little hacky...
I create a variable and try to change it and if it throws an error then it's a const variable,.
I create a variable and try to change it on the {} braces, if the value is different then it was initially created then it's a var, if not then it's a let variable.

is it ok to declare javascript variable in if block and use it outside the block? [duplicate]

This question already has answers here:
How does hoisting work if JavaScript is an interpreted language?
(2 answers)
Are variables declared with let or const hoisted?
(7 answers)
Closed 4 years ago.
In most languages I would write
declare var1 = undefined
if (condition) {
var1 = value1
}
but in javascript, it seems its allowed to write
if (condition) {
let var1 = value1
} else {
var1 = value2
}
Am I misguided on this?
Yes you can when you use var.
Not when you use let and const because they are block scoped.
Example for var
if (true) {
var var1 = 1
}
console.log(var1);
Example using let
if (true) {
let var1 = 1;
}
console.log(var1)
P.S :- In JS world using var is considered as bad coding practice.You should avoid using it until there is something you can't do with let and const.
In JavaScript, a variable can be declared after it has been used.
In other words: a variable can be used before it has been declared.
Hoisting is JavaScript's default behavior of moving all declarations to the top of the current scope (to the top of the current script or the current function).
So:
x = 5
// ... some other code ...
var x
will be translated to:
var x;
x = 5
// ... some other code
But it would only work this way if you used var to declare variable. If you use const or let it wouldn't work, because variables and constants declared with let or const are not hoisted.
Declaring variables using let or const is preferred way in modern javascript.
No, it's completely bad idea. If you want to use JavaScript variable both inside and outside of the if statement you can do it by declaring it outside the if statement.
let var1 = value1;
if (condition) {
var1 = value1
} else {
var1 = value2
}
This way you will only create a block scoped variable. But, if you use var var1 = value1 then it will declare globally scoped variable which is not what you wanted most probably.
To learn more about how variables works in javascript, you can checkout this awesome article. Happy coding :)
You can do this using let, but NOT in Strict Mode!
'use strict';
var condition = false;
if (condition) {
let var1 = 42;
console.log(var1);
} else {
var1 = 43;
console.log(var1);
}
// ReferenceError: var1 is not defined
It's recommended to declare var1 outside the scope of if statement:
'use strict';
var condition = false;
var var1 = 42;
if (condition) {
console.log(var1);
} else {
var1 = 43;
console.log(var1);
}
// => 43

javascript scope privacy breaking?

So I came across something very odd while working on a javascript project just now and here's a boiled down example of the situation I'm confused about:
function doSomething() {
for(var d = 0;d < 10;d++) {
var shouldBePrivate = 5;
}
for(var d = 0;d < 10;d++) {
console.log(shouldBePrivate);
}
}
When you call doSomething() the shouldBePrivate variable is accessible in the 2nd for loop.
Shouldn't that not be possible?
All local variables in javascript have function scope and not the block scope (atleast before ECMAScript 2015). Which means that declared variables inside the function , available for whole function.
What you are referring is block scope. Unfortunately noblock scope in Javascript till ECMA2015. From ECMAScript 2015, you can declare your variables with let which can be referred only with in the block and they die as soon as you come out of that block.
MDN docs says (with examples)
Block Scoping Rules
With var
Variables declared with var do not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java. For
example:
var x = 1;
{
var x = 2;
}
console.log(x); // logs 2
This logs 2 because the var x statement within the block is in the same scope as the var x statement before the block. In C or Java, the equivalent code would have outputted 1.
With let and const
By contrast, identifiers declared with let and const do have block scope:
let x = 1;
{
let x = 2;
}
console.log(x); // logs 1
The x = 2 is limited in scope to the block in which it was defined.
You've stumbled upon something called hoisting. Because all variables are scoped to their containing function, var statements are internally moved to the top of the function.
That means that the interpreter will actually be running this code:
function doSomething() {
var shouldBePrivate;
var d;
for(d = 0;d < 10;d++) {
shouldBePrivate = 5;
}
for(d = 0;d < 10;d++) {
// now it's easy to see why this works
console.log(shouldBePrivate);
}
}
As of ES2015, you can use the let keyword instead of var which is lexically scoped - i.e. scoped within blocks, meaning that let shouldBePrivate = 5; will not exist outside the first loop.
function doSomething() {
for(let d = 0;d < 10;d++) {
let shouldBePrivate = 5;
}
for(let d = 0;d < 10;d++) {
// Reference Error for shouldBePrivate
console.log(shouldBePrivate);
}
}

Javascript Undefined variable redefined inside function [duplicate]

This question already has answers here:
Why variable hoisting after return works on some browsers, and some not?
(5 answers)
Closed 6 years ago.
could you please help me understand why JS works this way here?
var timer = 3;
var func = function() {
alert(timer);
var timer = 5;
}
func();
It returns me "undefined".
If I do
var timer = 3;
var func = function() {
alert(timer);
timer = 5;
}
func();
it works as expected (alerts 3).
It is something with scopes that I didn't understand correctly.
Shouldn't JS overwrite the definition of "timer" after the alert?
Tested just on chrome.
Thank you guys.
var timer = 3;
var func = function() {
alert(timer);
var timer = 5;
}
This code becomes this when js interprets ;
var timer = 3;
var func = function() {
var timer; // Here local variable timer is undefined
alert(timer); // here local var timer alerts rather than global var timer
timer = 5; // here timer got initialized
}
This happens because of hoisting concept in javascript. You can read hoisting frome here
Variable hoisting is annoying in that javascript 'hoists' (send variable declarations) to the top of the current scope.
It doesn't however send initializations to the top of the current scope.
So:
var timer = 3;
var func = function() {
alert(timer);
var timer = 5;
}
becomes:
var timer = 3;
var func = function() {
var timer;
alert(timer);
timer = 5;
}
When it is interpreted.
Hoisting is (to many developers) an unknown or overlooked behavior of JavaScript.
If a developer doesn't understand hoisting, programs may contain bugs (errors).
To avoid bugs, always declare all variables at the beginning of every scope.
Since this is how JavaScript interprets the code, it is always a good rule.

Categories

Resources