understanding Let scope - javascript

My assumption with code is that for the second let x the code above it is in the temporal dead zone. Hence should not throw error.
Code
function f(condition, x) {
if (condition) {
let x = 100;
return x;
}
let x = 30; // <---- throw error
return x;
}
f(true, 1);

Well the problem here is that you are redeclaring the same variable x twice in the same function, so the variable x will be hoisted.
if (condition) {
//This x declaration is fine as it wasn't preceded with any others declaration inside the same block scope
let x = 100;
return x;
}
//Now this second x declaration will cause the hoisting problem
let x = 30; // <---- throw error
Here the second let x = 30; declaration is hoisting the x variable in your function scope. So conclusion is that you can't declare the same variable more than once in the same scope.
For further reading about varaible hoisting in Javascript you can check:
MDN Hoisting
reference.
A guide to JavaScript variable hoisting 🚩 with let and const article

Issues seem to be with x already being a function parameter having the same scope as the outer x. If i change function parameter x with y, the code works fine.
Code
function f(condition, y) {
if (condition) {
let x = 100;
return x;
}
let x = 30; // <---- doesnt throw error
return x;
}
f(true, 1);

Related

Why does this JavaScript code return an error?

I know in JavaScript only function declarations are hoisted, which means it should print 30 after running the function sum.
However it says diff is not defined, shouldn't it be hoisted?
sum(10, 20);
diff(10, 20);
function sum(x, y) {
return x + y;
}
let diff = function(x, y) {
return x - y;
}
It's because as you said, only function declarations are hoisted, not function expressions (assigning a nameless function to a variable). Following code works:
sum(10, 20);
diff(10, 20);
function sum(x, y) {
return x + y;
}
function diff(x, y) {
return x - y;
}
To declare diff the way you did, you must lift it to the top of your code:
let diff = function(x, y) {
return x - y;
}
sum(10, 20);
diff(10, 20);
function sum(x, y) {
return x + y;
}
Yes, let and const are hoisted but you cannot access them before the actual declaration is evaluated at runtime.
You are accessing the function before you initialize it.
So this should work,
let diff = function(x, y) {
return x - y;
}
function sum(x, y) {
return x + y;
}
console.log(sum(10, 20));
console.log(diff(10, 20));
let diff will hoist but at the moment when function diff(10, 20); will be called variable diff will not jet be defined with the function.
Google this topic function declaration vs function expression
Because Function Expressions are not hoisted like Function Declarations
Function expressions in JavaScript are
not hoisted, unlike function declarations. You can't use function
expressions before you create them:
console.log(notHoisted) // undefined
// even though the variable name is hoisted, the definition isn't. so it's undefined.
notHoisted(); // TypeError: notHoisted is not a function
var notHoisted = function() {
console.log('bar');
};
https://developer.mozilla.org/en-US/docs/web/JavaScript/Reference/Operators/function#function_expression_hoisting
You will need to use a Function Declaration if you want it to be hoisted.

passing variables across functions on javascript

I'm trying to pass variables across functions,
something like
function one() {
var x = 1
}
function two() {
var y = x + 1;
}
alert(y);
Is there a way to do it?
edit:Thanks everyone for being so helpful, but maybe I should have been more specific with my question.
You current way has x and y in the scope of the function, which means the other function doesnt know it exists. Also, its good practice to name functions according to what they do. 3 straightforward ways to do this.
Global
Params
Inline
Set two variables outside of the functions scope that any function can reach.
var x, y;
function assignOne() {
x = 1;
}
function addOne() {
y = x + 1;
}
assignOne();
addOne();
console.log(y);
Pass in a parameter to to the function and return values.
function one() {
return 1;
}
function addOneTo(x) {
return x + 1;
}
const y = addOneTo(one());
console.log(y);
Perform functions inline
var x = null;
function one() {
x = 1;
}
function two() {
return x + 1;
}
one();
const y = two();
console.log(y);
You will need to hoist the scope, by extracting the variable declaration to outside of the functions. That is to say, define x and y outside of the functions. Note that you can still update their values from within the functions. However, don't forget that you'll actually need to invoke both functions as well!
This can be seen in the following:
var x, y;
function one() {
x = 1;
}
function two() {
y = x + 1;
}
one();
two();
console.log(y);
If you really want to get variable declared in one method, return it
function one(){
var x = 1;
return x;
}
function two() {
var x = one();
var y = x + 1;
return y;
}
alert(two());
Seems like you want to have shared state between both functions instead of passing arguments. So, an object oriented pattern seems to be appropriate.
class Thing {
constructor() {
this.x = 1;
}
one() {
return this.x;
}
two() {
return this.x + 1;
}
}
const t = new Thing();
console.log(t.one());
console.log(t.two());
If you want to share variables between functions but don't want to declare them in global scope, you can use a closure like this:
(function() {
var x, y;
function one() {
var x = 1
}
function two() {
var y = x + 1;
}
one();
two();
alert(y);
})();

JS Closures - What is the value of x?

This is a thought exercise. I'm not doing anything with this code and the purpose is to better understand how closures work.
Thought Process:
x === 10 in global scope.
outer() function is called.
x === 20 in the global scope and local scope.
inner() function is called.
right side of 'var x' is expressed.
In x + 20, because x is not defined in local scope, it searches outer scope and finds x === 20.
var x = 20 + 20.
var x === 40.
return x.
result === 40.
However, the answer is 20. Why is this?
var x = 10;
function outer () {
x = 20;
function inner () {
var x = x + 20;
return x;
}
inner();
}
outer();
var result = x;
When the inner() function is called, the first thing that happens is var x.
This means the JavaScript interpreter first creates a variable named x to which it assigns undefined.
Then it runs the assignment expression x + 20, which is equivalent to undefined + 20 which is NaN.
Your variable result has nothing to do with your inner() function as you have a local variable (because of that var x) and you ignore the returned result.
In other words, your code is equivalent to just this:
var x = 10;
function outer () {
x = 20;
}
outer();
var result = x;
Because your inner function defined a local var x which will hide the global variable outside. And the outer function uses the global variable x and assign it to 20. Obviously, the global x is 20. Javascript will define every local variable before you call the function in the prototype chain.
var x = 10;
function outer () {
x = 20;
function inner () {
alert(x); // alert undefined
var x = x + 20;
return x;
}
inner();
}
outer();
var result = x;

js variable value in a function from which scope [duplicate]

This question already has answers here:
Javascript scoping of variables
(3 answers)
Closed 6 years ago.
i have this code in java script
var x = 5;
function f(y) { return (x + y) - 2 };
function g(h) { var x = 7; return h(x) };
{ var x = 10; z = g(f) };
z value is 15. why?
the expression (x+y)-2 is being evaluated as (10+7)-2.
why does x get the value of 10, and not the value of the previous
block, where x = 7?
thanks for the help
You can completely delete the first assignment. It gets overwritten before you call g(f).
Also, you can remove the parentheses of the last block as there is no block scope in JS (actually block scope got introduced with let, so you wanna use that instead).
var x = 5;
function f(y) {
// global variable x is 10 -> 10 + 7 - 2 = 15
return (x + y) - 2;
}
function g(h) {
// x gets declared locally - local value will be used
var x = 7;
return h(x); // f gets called with y = 7
}
x = 10; //global x gets changed
z = g(f);
... and always place your semicolons. Even though they maybe look optional but in some cases they are obligatory.
Value of variable x is 10 at global execution context.
When function f is finally called the value of the argument which is y, this y actually represent value of x at local execution context of function g, here x is 7.
var x = 5;
function f(y) {
return (x + y) - 2 ;
}; // value of global var x is 10, value of parameter passed is 7
// this value comes from the local var x of g function's execution context.
function g(h) {
var x = 7; return h(x); };
{ var x = 10; z = g(f); };
console.log(z);

Scope of variables in functions using javascript

Why the y is leaked outside the function as scope in JavaScript are bound to functions.
A detailed explanation would be fruitful.
var x = 0;
function f(){
var x = y = 1; // x is declared locally. y is not!
};
f();
console.log(x, y); // 0, 1
It's just syntax error.
The line var x = y = 1; Means:
Declare local variable x,
y = 1,
Declare global variable y (since it's not declared)
x = y;
Replace
var x = y = 1;
with
var x = 1, y = 1;
or
var x = 1;
var y = 1;
and you will get local variable y
http://www.w3schools.com/js/js_variables.asp
The reason the y variable is global is that in Javascript if you omit the var keyword from an assignment statement, the variable the value is assigned to is declared on the global object.
That means that if you wrote the f() function this way, declaring both x and y with the var keyword:
function f(){
var x, y;
x = y = 1;
};
Then both x and y would be local variables (local x shadowing the global one).
It's bad practice to assign a variable without declaring it (with the var keyword).
New versions of JS will throw an error on this. You can use EC5's strict mode to take advantage of this behavior:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
so you'd write your function this way:
function f(){
'use strict'
var x, y;
x = y = 1;
};
now if you forget to declare y you get an error yelling at you to do so.

Categories

Resources