store variable value inside a if statement - javascript

1st if condition:
if (currentQuestionIndex == 2) {
var xvalue = currentscore;
}
2nd if condition: (note: current score increments for every currentQuestionIndex)
if (currentQuestionIndex == 5 && currentscore ==xvalue) {
console.log('thanks for your participation')
}
I want to access the value of xvalue in 1st if condition and reference it in 2nd if condition. Is there any way to store value of a variable and reference it later without regards to if condition

Actually, you can access a variable declared with var inside if statement. A if block (or any block) does not create a new scope: in JavaScript, only a function do that.
This is valid (example from the docs):
if (true) {
var x = 5;
}
console.log(x); // x is 5
This happens because JavaScript interpreter scans your function before executing it, and keep track of all variable declarations (like moving it to the top).
So, the above code is equivalent to (interpreter perspective):
var x;
if (true) {
x = 5;
}
console.log(x); // x is 5
Quoting from MDN:
JavaScript before ECMAScript 2015 does not have block statement scope;
rather, a variable declared within a block is local to the function
(or global scope) that the block resides within.
As pointed, this behavior changes with the introduction of ECMAScript 2015 let.
if (true) {
let x = 5;
}
console.log(x); //x is not defined
So, to use your code as an example, this will run fine:
/* arbitrary values */
var currentQuestionIndex = 2;
var currentscore = 10;
if (currentQuestionIndex == 2) {
var xvalue = currentscore; //declared inside if block
}
if (currentQuestionIndex == 2 && xvalue == 10) { //I can read here
console.log('value of xvalue: ' + xvalue); //can read here too: will print 10
console.log('thanks for your participation')
}
Anyway, just because you can, doesn't mean you should. As a matter of readability and code organization, a recommended practice is to declare your variable at the beginning of your scope (global, if outside any function, or local, if inside a function).

Just define the variable xvalue outside of if statement:
///Just for testing
var currentQuestionIndex = 2
var currentscore = 2
///
var xvalue = 0;
if (currentQuestionIndex == 2) {
xvalue = currentscore;
}
///Just for testing
currentQuestionIndex = 5
currentscore = 4
console.log('xvalue: ' + xvalue)
///
if (currentQuestionIndex == 5 && currentscore == xvalue) {
console.log('thanks for your participation')
///Just for testing
console.log('xvalue: ' + xvalue)
///
}
And read about variable scopes, for example here.

You can set your xvalue variable outside of your if statement.
var xvalue = 0;
or simply:
var xvalue;
This way the variable is always able to be accessed by any other function, even if you haven't given it a value.

Just declare xvalue outside the first if like this:
var xvalue; // decalare it here so it can be accessed by both if statements (probably you'll have to initialize it with something)
if (currentQuestionIndex == 2) {
xvalue = currentscore; // don't redeclare it here so you won't shadow the above one
}
Read more about scopes, variables lifetime and shadowing!

Related

Can a function read the binding of another function?

I'm currently learning javascript and I would appreciate some help.
I've been playing around trying to create a program that would multiply two numbers without using the * operator. I already found an easier way to do it than my approach but I'd like to know why the code I wrote doesn't work:
function addToItself(a) {
a = a + a;
return a;
}
function times(b) {
for (count = 0; count < b; count++) {
addToItself(a)
}
return a;
}
function multiply (x, y) {
a = x;
times(y);
}
let output = multiply(5, 2);
alert(output);
Is it not working because the binding "a" in the addToItself function has a local scope and the multiply function can't read it or is it something else?
Thanks a lot in advance!
The issue is with the scope of each variable. In JavaScript, a variable declated within a function is scoped to that function. This means that a variable declared within a function can only be accessed within the function. Scopes are nested, so a variable declared globally is accessible inside a function too, though that's often discouraged.
Additionally, function arguments (such as a in addToItself and b in times) are treated like variables scoped to the function.
I would advise looking at the MDN docs for "scope" and familiarizing yourself with how variables are scoped in JavaScript.
I have included a fixed version of your code is below, for reference:
function addToItself(a) {
// I used a new variable here since reassigning to an argument is discouraged
const twoA = a + a;
return twoA;
}
console.log('5 + 5 = ' + addToItself(5));
function times(value, times) {
let temp = 0;
for (let count = 0; count < times; count++) {
temp += value;
}
return temp;
};
console.log('5 * 5 = ' + times(5, 5));
No you can't read variable inside another function, there are easier way, like
function multiply(x, y) {
var result = 0;
for (var count = 0; count < y; count++) {
result += x
}
return result;
}
console.log("5 * 2 = " + multiply(5, 2));

ReferenceError when using 'let' to declare variable through a ternary operator

I've seen code where a ternary operator is used to check whether or not a variable has been declared, and declare it if it has not been. For example:
var num = (typeof num === 'undefined' ? 1 : num);
console.log(num); //1
However, this does not work when using 'let' instead of 'var':
let num = (typeof num === 'undefined' ? 1 : num); //Uncaught ReferenceError: num is not defined
I know that compared to 'var', 'let' has block scoping and prevents redeclaration. I'm unsure how this would cause the ReferenceError in the case above. Could anyone shed some light as to what's going on here? Thanks!
You've run into something called hoisting.
Hoisting affects var declaration, but not let or const.
In short words, hoisting moves every var declaration to the top of the code. Meaning for this code:
x = 1;
var y = x + x;
var x;
It is translated to:
var y; // y is declared, but undefined (thus y === undefined)
var x; // x is declared, but undefined (thus x === undefined)
x = 1; // x is defined
y = x + x // y is defined
Which is why you don't get an error, because x is declared, then defined.
But that is not the case for let and const:
x = 1;
let y = x + x;
let x;
will throw an error, because you used x before it is declared.
EDIT
Read Felix's comment below for details.
Not the best way to check variable existence. You should not do it by accessing variable.
If you have to do it do it using:
var barIsDeclared = true;
try{ bar; }
catch(e) {
if(e.name == "ReferenceError") {
barIsDeclared = false;
}
}
You get reference error in case of constand let variables. It may appear that they are not hoisted in the first iteration phase but that is not true.
Anyway, this is how I test variable existence and it works with no issues.
You're just trying to access to it before initializing it.
let num;
num = (typeof num === 'undefined' ? 1 : num);
console.log(num); //1
this is the actual answer you want.

JavaScript Global variable value changes on Function value

Why am i getting two different results from the below code. The only change i am doing is passing the value to a function, in first code i am getting the value of global variable "count" as 10 and in the second code the global variables("count") value changes to 30.
function addTen(count) {
count = count + 20;
return count;
}
var count = 10
var result = addTen(count);
console.log(count); //10
console.log(result); //30
function addTen(num) {
count = num + 20;
return count;
}
var count = 10
var result = addTen(count);
console.log(count); //30
console.log(result); //30
In your second function, the statement
count = num + 20;
assigns to the global variable (it's the only count in scope). To make it a local variable for the function scope only, and not affect the global, use
var count = num + 20;
In your first function, the parameter count implicitly declares such a local variable, shadowing the global variable of the same name.

What happens when a JS closure is made with a block-scope variable?

A little while ago, I asked a question using this sample JS code...
for (var myindex = 0; myindex < mylist.length; myindex += 1) {
var copyindex = myindex;
MyAsync(mylist[myindex], function () { alert(copyindex); });
}
(The answer was essentially to call a named function, which keeps each variable in the loop separate.)
My question for today is, what's actually going on in this sample code above? Each alert call is being passed the same copyindex variable, even though a new one is being declared each time the loop goes around.
Is this behavior required by the JS language? (That by declaring a variable with block scope, I'm really declaring it at the top of the function.)
Or, is this perhaps an implementation detail of the few browsers I tested with, and future JS platforms are under no obligation to link the many instances of copyindex together?
Each alert call is being passed the same copyindex variable, even though a new one is being declared each time...
That's a common misunderstanding. var does not have block scope, so your code really is this:
var copyindex;
for (var myindex = 0; myindex < mylist.length; myindex += 1) {
copyindex = myindex;
MyAsync(mylist[myindex], function () { alert(copyindex); });
}
More (on my blog): Poor, misunderstood var and, of course, in the specification — it's covered in §10.5 - Declaration Binding Instantiation.
ES6 will introduce block-scoped variables via the let keyword. Where you use the let keyword matters quite a lot.
Let's take a simpler example, starting with var:
for (var x = 0; x < 3; ++x) {
setTimeout(function() { console.log("x = " + x); }, 0);
}
console.log("typeof x = " + typeof x);
We know that will give us
number
3
3
3
...because var is hoisted to the top of the scope, and so the same x is used by all three functions we create, and x exists outside the loop. (We see the typeof result first, of course, because the others happen after the minimal timeout.)
If we use let instead, in that same place:
for (let x = 0; x < 3; ++x) {
setTimeout(function() { console.log("x = " + x); }, 0);
}
console.log("typeof x = " + typeof x);
We get
undefined
3
3
3
...because x is scoped to the loop, not loop iterations. All three functions still use the same x, the only difference is that x doesn't exist outside the loop.
But if we use let within the body:
for (let n = 0; n < 3; ++n) {
let x = n;
setTimeout(function() { console.log("x = " + x); }, 0);
}
console.log("typeof x = " + typeof x);
We get
undefined
0
1
2
...because now x is scoped to the body of each iteration, not the loop as a whole.
You can try these yourself using NodeJS, just be sure to give it the --harmony flag to enable ES6 features.

Javascript code semantics

if(myVar = img.parent('a').length > 0){
var Y = 1;
}else{
var Y = 2;
}
When I run this code myVar (being announced for the first time) takes the value of img.parent('a').length > 0 and becomes either false or true depending on the case.
First Question:
Is this a correct way of defining myVar?
Second Question:
Am I defining Y for the second time? Is my second 'var' excess?
i.e. should i just write Y = 2;
First question: IMO, using an assignment on the condition of the if statement, might cause confusion, also if myVar is not declared previously with the var statement it might become a global variable.
Second question: No, you aren't re-declaring Y a second time, actually Y is defined before any assignment, it is hoisted to the top of its enclosing scope.
This is how actually var behaves in your code:
var Y; // declared and initialized with `undefined`
if (myVar = img.parent('a').length > 0) {
Y = 1; // assignment
} else {
Y = 2; // assignment
}
You can observe this behavior with the following example:
var Y = 'foo';
(function () {
alert(Y); //alerts `undefined`
var Y;
})();
As you see, the alert is before the var declaration in that function, but since the var statement is hoisted, the Y variable from this new scope is set up before the execution, when the Variable Instantiation process takes place.
The most straight forward approach, would be to declare and assign myVar:
var Y, myVar = img.parent('a').length > 0;
if (myVar) {
Y = 1;
} else {
Y = 2;
}
// Or Y = myVar ? 1 : 2;
Or even shorter, in a single var statement:
var myVar = img.parent('a').length > 0,
Y = myVar ? 1 : 2;
//...

Categories