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;
//...
Related
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.
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.
In the following example, JavaScript seems to be completely ignoring my return statement, and just carrying on executing code.
var x = 1;
(function() {
x = 2;
return;
var x = 3;
})();
console.log(x); // Outputs 1 in both Chrome and FF
Surely the code should output 2? If I remove the var keyword from var x = 3, it outputs 2 as expected. Is there some strange compiler optimization at work here?
No, the code shouldn't output 2 because variable declarations are hoisted so your code is equivalent to
var x = 1;
(function() {
var x;
x = 2; // changes the internal x variable
return;
x = 3; // does nothing because it's not reached
})();
console.log(x); // Outputs the outside x, which is still 1
The line
x = 2;
only changes the internal x variable which shadows the outside one.
The scope of a non global variable is the entire function in which it is declared. From the start of this function to its end.
x = 1;
alert(x);
var y = function() {
alert(x);
var x = 2;
alert(x);
}
y();
The result of the 3 alerts is: 1, undefined, 2 (Chrome 25)
My question is: why the second alert is undefined? Why not 1? Isn't there a global variable x?
Due to hoisting, this is what gets executed:
x = 1;
alert(x);
var y = function() {
var x; // <-- this gets hoisted up from where it was.
alert(x);
x = 2;
alert(x);
}
y();
At the start of function y(), the local variable x is declared but not initialized.
The variable declaration in the function is hoisted to the top. So it technically looks like this:
var y = function() {
var x;
alert(x);
x = 2;
};
The local variable overshadows the global one. That is why the alert returns undefined.
Since scope in JavaScript is a function object. When you execute some code in a function(your code sample), "alert(x)" will find if there's any definition of "x" in the function. So, there's a "var x = 2" in this function. But the JavaScript runtime will explain your code like this:
x = 1;
alert(x);
var y = function() {
var x;
alert(x);
x = 2;
alert(x);
}
y();
So, the x in the second alert is "undefined" not "1". So when you declare some variable in a function, I recommend you to declare the variables in the top of your function.
Consider the following two JavaScript snippets:
var x = 2;
function f() {
var y = x;
eval('var x;');
return y;
}
vs.
var x = 2;
function f() {
var y = x;
var x;
return y;
}
The only difference is I've replaced eval('var x;'); with var x;.
The first one returns 2, but the second one returns undefined. Why?
Variable declarations are hoisted by the parser to the top of the lexical scope. In the second block of code, the way it's actually run is:
function f() {
var x, y;
y = x;
return y;
}
Function declarations are also hoisted. The net effect is that a variable declaration should be considered to always include the entire lexical scope in which it appears. If variable x is declared with var anywhere in a function, then every reference to x in that function is to the local variable.
In your first example, the eval() line is just a regular expression statement, so it's executed in order of its appearance in the function.
Because with the second one, the var is hoisted* to the beginning of the function, before any other statements are executed.
So its as though you code was this:
var x = 2;
function f() {
var x, y
y = x;
return y;
}
But with the first one, the var x is part of the eval() expression, so it doesn't have the opportunity to be hoisted* as in the second one.
*The term "hoisted" is not an official term. Its just a word that people use to describe the fact that declarations happen before any expressions are evaluated within the execution context. Function declarations are also hoisted.
That's because when the interpreter is in scope of function it sets value undefined to all variables which are declared inside it (with var keyword prefixed). It's no matter where you've put the declaration, if there's a variable declaration inside a function the variable's value will be undefined until you set it's value explicitly. In the first case you have eval('var x;') which is still not evaluated when the value of y is being set. That's why the value of y is 2, because the value of the variable x in the upper scope is 2.
The same will be here:
var x = 2;
function foo() {
var y = x;
console.log(y); //undefined
console.log(x); //undefined
var x = 3;
}
function bar() {
var y = x;
console.log(y); //2
}
var x = 2;
function foobar() {
console.log(x); //undefined
var x;
console.log(x); // undefined
x = 3;
var y = x;
console.log(y); //3
}
The eval is evaluated just as a regular expression.