Variable hoisting examples [duplicate] - javascript

This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 7 years ago.
Hi I have a snippet of code. I am confused about change of value x1 when I remove non-related part of same code. I searched about it and I came to know that it has to do with hoisting. But the value x1 is still unclear even with hoisting concept for me. Can someone please make me clear on this?
var x = 10;
function main() {
document.write("<br>x1 is " + x);
x = 20;
if (x > 0) {
var x = 30;
document.write("<br>x2 is " + x);
}
var x = 40;
var f = function(x) {
document.write("<br>x3 is " + x);
}
f(50);
}
main();
The output of this code is:
x1 is undefined
x2 is 30
x3 is 50
If I change this code to:
var x = 10;
function main() {
document.write("<br>x1 is " + x);
}
main();
The output is:
x1 is 10

So what is happening here is a common pitfall.
The simplest way to put this is. When you set var x = 30 inside your main function, you are actually redefining the scope that var x = 10 had for use inside this function. This has to do with how Javascript executes and scope.
By defining x inside the function, your scope for x has changed. Below is an example of what I mean and a version of your code that works
Example:
var test = 'test';
function run(){
console.log(test);
var test=1;
}
Your Code Updated:
var x = 10;
function main() {
console.log("<br>x1 is " + x);
x = 20;
if (x > 0) {
x = 30;
console.log("<br>x2 is " + x);
}
x = 40;
var f = function(x) { console.log("<br>x3 is " + x); }
f(50);
}
main();
Good question btw.
Since this is somewhat of a very interesting scope of how Javascript executes, consider the following code and its outputs to get the full idea
var test = 'test';
function run(){
console.log(test);
test=1;
console.log(test);
var test=2;
console.log(test);
}
console.log(test);
run();
console.log(test);
Very interesting to see how this reacts.

All variable and function declarations get "hoisted" or moved to the top of their scope. The undefined value for x is caused because the var x statement gets moved up to the top of main however the assignment = 30 does not.
So, your code will read more like this:
var x = 10; // x is 10
function main() {
var x; // x declaration is "hoisted"
document.write("<br>x1 is" + x); // x1 is undefined
x = 20; // x is 20
if (x > 0) {
x = 30; // x is 30
document.write("<br>x2 is" + x);// x2 is 30
}
x = 40; // x is 40
var f = function(x) { // x is 50
document.write("<br>x3 is" + x);// x3 is 50
}
f(50);
}
main();
You can read more about Hoisting here: JavaScript Scoping and Hoisting

Related

I couldnt call a value from other function

The js code has 3 functions. I want to call values from the 2 functions and execute them in the 3rd function.
function first() {
var x = 2
var y = 3
var z = x * y
}
first()
function second() {
first();
var z;
var a = z - 1
}
second()
function third() {
first();
second();
var a
var z
var ans = a * z
console.log(ans);
document.getElementById("ans_html").innerHTML = precision(ans);
}
third()
<div id="ans_html"></div>
The expected outcome was 30.
But the output was "NaN".
In most languages, including JS, variables have "scope" (mdn). If you want to share data between function's, you can either
1) return values (mdn),
function first() {
var x = 2
var y = 3
return x * y;
}
function second() {
let z = first();
return z - 1
}
function third() {
let z = first();
let a = second();
var ans = a * z
console.log(ans);
}
third();
2), less conventionally, modify a param obj since they're are passed by ref.
let func = param => {
param.x = 3;
param.y = 4;
};
let a = {};
func(a);
console.log(a);
You will need to either create global variables which is considered a bad practice, or pass values around as parameters.
Global variables:
var a
var x
var y
var z
function first() {
x = 2
y = 3
z = x * y
}
function second() {
a = z - 1
}
function third() {
first()
second()
let ans = a * z
console.log(ans);
}
Passing Parameters:
function first(x, y) {
return x * y
}
function second(z) {
return z - 1
}
function third() {
let x = 2
let y = 3
let z = first(x, y)
let a = second(z)
let ans = a * z
console.log(ans);
}
Judging based on your code, you likely should take a look into how JavaScript scopes variables based on using the keyword var vs let. I hope this helps!
You have two major issues:
Your variables a and z are not global variables. They are defined within the function itself so you cannot access those variables outside of that scope (see this)
I would not fix your code to adhere to the first issue. You don't need global variables here, you just need to return the result so you can call your functions later. In the long run, I would assume you want to add arguments to your functions, but the below is an example of how to do what you're trying to accomplish by simply returning the result in your functions.
NOTE I don't know if you have a custom precision function or what. So, I added an empty function that just returns the input. You can probably remove this.
function precision(num) {
// Insert whatever is in your precision function here...
return num;
}
function first() {
var x = 2
var y = 3
var z = x * y
return z;
}
function second() {
var z = first();
var a = z - 1
return a;
}
function third() {
var a = second();
var z = first();
var ans = a * z
console.log(ans);
document.getElementById("ans_html").innerHTML = precision(ans);
}
third()
<div id="ans_html"></div>
This is not the best design pattern, but if you want to achieve this in this way, the code is going to look like the one below. You need to return the result of the function in order to get it in another function and use it.
function first() {
var x = 2
var y = 3
return x * y
}
function second() {
var z = first()
return z - 1
}
function third() {
var a = first()
var z = second()
var ans = a * z
console.log(ans);
// document.getElementById("ans_html").innerHTML = precision(ans);
}
third()
<div id="ans_html"></div>

Block scope in ES5

I am having a problem with an assignment. This is the assignment:
Given following function.
let rechne = function(x,y,operation) {
let ergebnis = x - y;
if (!operation) {
let ergebnis = x + y;
console.log(ergebnis);
}
return ergebnis;
}
Rewrite the function so that the desired block scope of the variables
can be achieved in ES5.
So I wrote this:
let rechneScope = function(x,y,operation) {
(function(){
let ergebnis = x - y;
})()
if (!operation) {
(function(){
let ergebnis = x + y;
console.log(ergebnis);
})()
}
return ergebnis;
}
Presumed I called that function in a console.log like console.log(rechneScope(10, 2))
I would expect the first variable to be 8 and the second one to be 12.
But when I reload the browser, the console always prints 12 for the second variable and for the first variable the result differs. Sometimes 2, sometimes 8, sometimes 15. I am really confused. Why is this happening?
First, you're assumption that the desired output is 8 then 12 is wrong. The first console.log that gets executed is the one with ergebnis = x + y, so you should see 12 then 8.
Next, let was introduced in ES6 so if you're limiting yourself to ES5, you're only allowed to use var.
Finally, make sure your you wrap the entire scope of each variable in an IIFE. You have return ergebnis outside of the first function so that variable won't be in scope anymore at the time that line of code executes.
The correct implementation would be something like this:
var rechneScope = function(x, y, operation) {
return (function() {
var ergebnis = x - y;
if (!operation) {
(function() {
var ergebnis = x + y;
console.log(ergebnis);
})()
}
return ergebnis;
})()
}
console.log(rechneScope(10, 2))
I know it's not part of your assignment, but just for reference, Babel doesn't bother with trying to emulate ES6 scope. Here's how the same thing would be compiled by Babel:
"use strict";
var rechne = function rechne(x, y, operation) {
var ergebnis = x - y;
if (!operation) {
var _ergebnis = x + y;
console.log(_ergebnis);
}
return ergebnis;
};
You are making minor mistakes.
You are using the let keyword which cares about the scope and
because of that your 'ergebnis' is undefined in return.
You are not printing the output in first block.
Solution is to remove return statement and print the answer in each block. You will get the desired result
let rechneScope = function(x,y,operation) {
(function(){
let ergebnis = x - y;
console.log(ergebnis);
})()
if (!operation) {
(function(){
let ergebnis = x + y;
console.log(ergebnis);
})()
}
}
rechneScope(10, 2);

Javascript Function Call [duplicate]

This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 6 years ago.
The question is really simple but i searched everywhere couldn't get an answer.
add();
function add()
{
//function code here
}
The above code works in JavaScript even though function call is before function definition but wouldn't work in language such as C or C++. Could anyone tell me why?
It's known as hoisting, and it's definitely a trap for beginners!
Basically, if you take this code:
var x = 21;
var y = add10(x);
function add10(n) { return n + 10; }
after hoisting, it is evaluated like this:
function add10(n) { return n + 10; }
var x;
var y;
x = 21;
y = add10(x);
Because the declarations are separated from the definitions, and "hoisted" to the top.
Funnily enough, this would fail:
var x = 21;
var y = add10(x);
var add10 = function (n) { return n + 10; }
because it is evaluated like this:
var x;
var y;
var add10;
x = 21;
y = add10(x); // add10 is not a function (yet...)!
add10 = function (n) { return n + 10; }
It's called hoisting.
The javascript engine first looks for function declarations and 'hoists' them to the top before your actual code starts running.
Here's the documentation: http://www.w3schools.com/js/js_hoisting.asp

How does global variables in JavaScript work? [duplicate]

This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 8 years ago.
I m a newbie to javascript. I usually program in Java. I am confused by this following code snippet.
<script>
x = "foo";
function bar(p){
if (p){
document.writeln("x = " + x);
} else {
var x = "baz";
}
}
bar("baz");
</script>
When I run the above code snipped its printing
x = undefined
Why does it print undefined, since x is a global variable it should print foo right ? Can anyone explain ?
since x is a global variable it should print foo right
It would if it wasn't shadowed by the var x = "baz"; declaration further up in your function; due to hoisting it will execute the function as if you wrote
function bar(p){
var x; // = undefined
if (p){
document.writeln("x = " + x);
} else {
x = "baz";
}
}
To make the code do what you want, you could simply write x = "baz"; instead of var x = "baz";.
try this output is x = foo
var x="foo";
function bar(p){
if (p){
document.writeln("x = " + x);
} else {
x = "baz";
}
}
bar("baz");

Why it is printing i value (it is already outside the scope)?

In JavaScript why i value is printed when we are printing outside the scope
test();
function test(){
for(var i=0;i<10 ;i++){
console.log(i)
}
console.log('outside'+i)
}
As comparison to Java it is giving compile error?
for(int x = 10; x < 20; x = x+1) {
System.out.println("value of x : " + x );
}
System.out.print("value o " + x );
JavaScript has function scope not block scope (C, C#, C++, Java and many other programming languages have block scope). In JavaScript a variable defined anywhere inside the function will be visible anywhere in the function:
function test() {
console.log(x); // logs undefined, because x is a variable that has no value yet
if (true) {
x = 42;
} else {
var x = 5; // x is not set to 5, but it is acknowledged as a variable
}
console.log(x); // logs 42 because the value in variable x has been set to 42
console.log(y); // Error because y is not declared
}
One thing you might see mentioned regarding this is var hoisting. This means the JS interpreter will act as if all the var statements in a scope (function or global) are moved at the begining of that scope:
function foo() {
console.log(x,y);
var x = 4;
var y = 2;
var x = 0;
}
// is equivalent to:
function foo() {
var x,y;
console.log(x,y);
x = 4;
y = 2;
x = 0;
}
More details on MDN
Also, note the difference between var and let from ECMAScript6
The scope of i in this case isn't the for loop, but the test() function.

Categories