I have been using python for a while now, and have just started learning javascript. In javascript you can, as I understand it, declare a variable without assigning a value to it (var cheese compared to var cheese = 4) in what situation would you want to declare a variable but not assign a value to it straight away?
Consider this snippet.
if (someCondition) {
var x = 5;
} else if (someOtherCondition) {
var x = 4;
}
if (x) {
doFunc();
}
Since x needs to exist for the doFunc to run, you simply add an undefined declaration above. var x; so that the if (x) doesn't return an error.
You do this when you want the value of the variable to be undefined.
var cheese;
console.log(cheese); // undefined
It's simpler than
var cheese = undefined;
The undefined value doesn't seem much useful, but this will allow to assign some other value later.
var cheese; can be perfectly useful (even if you never assign anything to it). Of course it's a shorter way to type var cheese = undefined;, but that's not the only reason…
Using var declares a local variable, and this has a nice property: it hides variables from parent scopes.
There's another part to your question:
If we're going to assign a value to var cheese anyway: why not assign immediately?.
Answer: it may be fine for your algorithm to return cheese without ever assigning anything to it — i.e. "undefined is valid".
Here's an example which illustrates how var hides variables from parent scopes:
var a = 3;
console.log(a); // prints 3; "a" is defined in this scope
function findEvenNumber(numbers) {
var a; // we declare this local variable, to ensure that we do _not_ refer to the variable that exists in the parent scope
numbers.forEach(function(number) {
if (number % 2 === 0) {
a = number;
}
});
return a; // if no even number was found, it returns undefined (because we never assigned anything to a)
}
findEvenNumber([1, 2]); // returns 2;
console.log(a); // prints 3; the "a" in this scope did not get overwritten by the function
Speculation: maybe the var cheese; syntax exists in ECMA to enable programmers to declare all variables at the beginning of their function. Such a convention was enforced by the C89 compiler, and some people grew fond of it.
Related
I am creating variable and using it in for statement
for(var i = 0; i < 10; i++) {
console.log(i)
}
It is working properly and resulting from 1-10;
When I write same in the if condition
if(var value = 10) {
console.log("Evaluate");
}
It is resulting Unexpected token var.
When I declare a variable (var a = 10), resulting the same error. Is there any issue.
An if statement only accepts an expression inside (something that evaluates to a value). Something like var value = ... is a statement - rather than evaluating to a value, it does something (namely, creates a local variable bound to the name value). So, since var value = ... cannot be evaluated as an expression, an error is thrown.
Some things can be evaluated both as statements and expressions (such as functions), but variable creation is not one of them.
Note that variable assignment is possible inside an if, because assignment does evaluate to the value assigned:
var value;
if(value = 10) {
console.log('value now has the value 10');
}
But that's really confusing to read - a reader of the code will likely immediately worry whether that's a typo or not. Better to assign variables outside of an if condition, whenever possible.
Only use var when you want to create a new variable. If you simply want to check a variable (for example, check whether the variable named value is 10), then just print that variable name, and use a comparison operator (===, not =):
if (value === 10) {
// do stuff
}
When you write
var value = 10
actually evaluated as the following statements:
var value;
value = 10
You can not write statement in if as condition, as the condition must be only expression:
An expression that is considered to be either truthy or falsy.
Declare and initialize the variable outside. Use proper operators.
var value = 10;
if(value == 10) {
console.log("Evaluate");
}
else {
console.log("Hello");
}
You need to declare the variable like this:
var value = 10;
if(value == 10) {
console.log("Evaluate");
}
I want to assign a value to a variable when a condition is verified like this
if (k<12){
var Case=4;
}
The problem when i call this variable to be printed in the body of the page i get undefined
document.write(Case);
Basically your var statement gets hoisted and assigned with undefined.
Variable declarations, wherever they occur, are processed before any code is executed. The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global. If you re-declare a JavaScript variable, it will not lose its value.
Order of execution:
var Case; // hoisted, value: undefined
if (k < 12) {
Case = 4;
}
You are getting undefined because you have not actually defined it. You are defining it when the condition is true. You should write the code like this.
var Case = null;
var k = 0;
if(k > 14) {
Case = 3;
}
document.write(Case);
I hope it was helpful.
var Case = 0;
if(k<12){
Case = 4;
}
document.write(Case);
You need to define it first so if k<12 == False it wont be undefined.
So in my js code I have some global variable that changes its value several times, for example
var x = 0;
...
x = 10;
...
x = 5;
Is there any possibility to get "history" of x without saving its value in other variables? Like, is there some function to detect that at some point of time x was equal to 10?
No, once a value is assigned to a variable, that variable's previous value is overwritten. It isn't retained anywhere. (If it were, it would be a nightmare for memory management.)
You could make an object property that retained a history if you wanted, by using a setter function; rough example:
var obj = {
_fooValue: undefined,
fooHistory: [],
set foo(value) {
this.fooHistory.push(this._fooValue);
this._fooValue = value;
},
get foo() {
return this._fooValue;
}
};
obj.foo = 0;
obj.foo = 5;
obj.foo = 42;
console.log(obj.fooHistory);
In that example, the history doesn't contain the current value, just the previous ones, and it stores the current value in another object property which means code could bypass the setter. There are lots of tweaks you could do. If you thought it was important, you could lock it down more:
var obj = (function() {
// These two vars are entirely private to the object
var fooHistory = [];
var fooValue;
// The object we'll assign to `obj`
return {
set foo(value) {
fooHistory.push(fooValue);
fooValue = value;
},
get foo() {
return fooValue;
},
get fooHistory() {
// Being really defensive and returning
// a copy
return fooHistory.slice(0);
}
}
})();
obj.foo = 0;
obj.foo = 5;
obj.foo = 42;
console.log(obj.fooHistory);
You can use variable like array and unshift next value to this array. And to use it take first element:
var x = [];
...
x.unshift(10);
...
x.unshift(5);
var currentX = x[0];
var allValues = x;
Yes there is. Using the Time Travelling debugging in Microsoft Edge browser. Check this out.
I'm not JS specialist, but as common idea for any OOP language, I would suggest to create special class for x (inherited from Integer in your example), which has overriden setter and some history array list. So, when you set a new value it stored in your history.
You need change only the variable type, not the code, which works with that. I also don't think there is some standard solution for this in any language. Probably, some dynamic introspectors, but those would be even more complex than my idea.
How would I reference a dynamic local variable? This is easily accomplished with a global variable:
myPet = "dog";
console.log(window["myPet"]);
How would I do the same in a local scope?
Specifically what I'm trying to do:
myArray = [100,500,200,800];
a = 1; // Array index (operand 1)
b = 2; // Array index (operand 2)
Depending on the situation, I want to evaluate a<b or b<a
To accomplish this, I set two variables: compare1 and compare2
compare1 will reference either a or b and compare2 will reference the other
Evaluate compare1 < compare2 or vice-versa
The following works perfectly with global variables. However, I want a and b to be local.
compare1 = "b"; compare2 = "a";
for(a=0; a<myArray.length; a++){
b = a+1;
while(b>=0 && myArray[window[compare1]] < myArray[[compare2]]){
/* Do something; */
b--;
}
}
If in the above I set compare1=a then I would have to reset compare1 every time a changed. Instead, I want to actually [look at/point to] the value of a.
Use an object instead of a set of separate variables instead. (I can't think of a real world situation where you would want to use a dynamically named variable where it isn't part of a group of logically related ones).
var animals = { dog: "Rover", cat: "Flopsy", goldfish: "Killer" };
var which = 'dog';
alert(animals[which]);
You can accomplish this with eval, however use of eval is highly discouraged. If you can wrangle your needs into David Dorward's recommendation, I'd do that:
var myPet = 'dog';
var dog = 'fido';
eval("alert(" + myPet + ")"); // alerts "fido"
you can reference a local variable globally if it is returned by a function.
function dog(name) {
var local = name;
return local;
}
myPet = dog('spike');
alert(myPet);
I was reviewing some today, when I encountered the following convention :
TestParam(1);
function TestParam(p){
var p = p + 1;
alert(p); // alerts '2'
}
Now, obviously, the developer didn't mean to delcare 'p' within the function, instead maybe meaning:
p = p + 1;
But the code still worked, i.e. the value alerted was "2". So it got me to thinking. What would happen in the following scenario:
var a = 1;
TestParam(a);
alert(a); // alerts "1"
function TestParam(p){
var p = p + 1;
alert(p); // alerts '2'
}
Again the alerts were as I suspected (as intimated in the comments above). So then I was curious as to what would happen if I used an object:
var a = { b: 1 };
TestParam(a);
alert(a.b); //alerts 1
function TestParam(p) {
var p = {b:p.b + 1};
alert(p.b); //alerts 2
}
So, in this instance, JavaScript has 'remembered' the variable a, even though when it is passed to TestParam as p, p is redeclared.
Now if I were to have done the following within the function, then both alerts would have been "2"
p.b++;
//var p = {b:p.b + 1};
I.e. it would have modified the member b of the original object. I get this. Its the previous scenario that baffles me!
I realise this is quite a hypothetical question that is unlikely to carry much real-world usefulness, but it still made me quite curious, as to what is going on in the background, and how exactly JavaScript is scoping and referencing these variables.
Any thoughts?
Variables are scoped to the enclosing function in JavaScript. And you can declare them as many times as you like.
Objects are not tied to variables; many variables can refer to the same object. (This is sometimes called aliasing.) This is what's happening in your last example. JavaScript has not "remembered" the variable a at all; rather, p and a refer to the same object, so when it is changed via p, you can see those changes via a.
Here's an example that might make more sense to you. Sometimes a person has more than one identity.
var Clark = new Person;
var Superman = Clark; // Maybe not everybody needs to know these two are
// the same person, but they are.
Clark.eyes = "brown";
alert(Superman.eyes); // should be brown, right?
Knowing the rules of the language you're using has tremendous "real-world usefulness". Not understanding these two rules is the source of a lot of confusion and bugs.
Javascript generally passes all arguments to functions by reference except when the argument is a number or a string. Javascript passes numbers and strings by value which is why your first example works the way it does.
I believe there's a typo in your code. I think you mean:
function TestParam(p) {
var p = {b:p.b + 1}; // p.b, not p.a (p.a == undefined)
alert(p.b);
}
In your example:
var a = { b: 1 }; // "a" is defined in the global scope
TestParam(a);
alert(a.b); // alerts 1
function TestParam(p) {
var p = {b:p.a + 1}; // "p" is defined in TestParam()'s scope
/* But not until after the expression on the right side of the assignment
has completed--that's why you can use p.a
alert(p.a); //alerts 2
}
At first, "p" is passed as a reference to the global variable "a", but then you redefine it in the first line. So, for example:
var a = { b: 1 };
alert(a.b); // Alerts 1
TestParam(a);
alert(a.b); // Alerts 2
TestParam(a);
alert(a.b); // Alerts 3
function TestParam(p) {
p.b++;
}