I saw that line in some code
window.a = window.b = a;
How does it work?
Does the following always return true?
window.a == a
it means
window.b=a;
window.a=a;
OR You can say.
window.b=a;
window.a=window.b;
two assignments in a single statment
and
And one more thing
window.a==a right?
yes this is Right. It will return true
This assignment runs from right to left, so at first 'window.b' will be assigned with 'a' value then 'window.a' will be assigned with 'windows.b' value.
You can break this multiple assignment like this and get the same results:
window.b=a;
window.a=a;
You should be also aware of something like scoping.
If you run this code in global scope, eg simple script like this:
<script>
var a = 10;
window.a = window.b = a;
</script>
window.a==a is true, because 'a' and 'window.a' are the same variables. 'a' is really a property of 'window' object. All global variables are properties of 'window' object. Knowing that you can write you code like this, and this code will be corresponnding:
<script>
var a = 10;
a = b = a;
</script>
But if you put this code in a function, it runs in function scope, eg:
<script>
function ex() {
var a = 10; // this is local variable
window.a = window.b = a; // this time window.a != a
}
</script>
Same as:
window.b = a;
window.a = a;
And no, window.a and a is not always equal. Typically it is only equal on the global scope in a web browser JavaScript interpreter.
The a and b properties on the window are being assigned to the value of a. Yes, if this code is executed in the global scope, a and window.a are the same.
var a = "foo";
//window.a and a are the same variable
window.a = "bar";
a; //bar
function f(){
var a = "notfoo";
//window.a is a different variable from a, although they may take the same value
window.a = "baz";
a; //notfoo
}
It's the same like:
window.b=a;
window.a= window.b;
window.a == a will be true in this case, after the statements above. There are some cases that it will be false, for example: when a is a global variable.
And one more thing: please find more informative title for your question next time.
Actually, window.a==a can be false if a has the value Number.NaN. That's because Number.NaN is not equal to any value, including itself.
Related
Run below code in Node environment. Running it in browser console doesn't allow to redeclare variable of var.
console.log(a);
var a = 5;
According to hoisting, the above code is going to look like this
var a = undefined;
console.log(a); // undefined
a = 5;
a variable is being hoisted to the top of the file. JS Engine allocates memory for this variable before the execution. The question is why below code consols 5 instead of undefined.
var a = 5;
console.log(a);
var a = 6;
I'm looking at this code and imagining that it's going to look like this:
var a = 5;
var a = undefined;
console.log(a); // undefined
a = 6;
I'd like to be sure of the answer instead of guessing. The JS Engine is smart enough to see that a variable is already declared and is going to ignore the next var expression and rehoisting in such case? So the output should be looking like:
var a = 5;
console.log(a); // 5
a = 6;
So it's like:
JS Engine sees for the first time declaration (in this case along with initialization) of a variable so it's allocating memory.
JS Engine sees for the second time declaration of a variable but is going to ignore the hoisting because variable of given name is already in the memory.
Am I wrong in something?
Preface: In modern JavaScript, var should never be used. Use let or const.
The JavaScript engine handles var in two steps:
Upon entering the global scope or a function scope, it processes every var in the entire scope, defining variables for the them initialized wit the value undefined. If a variable is declared more than once with var, it's exactly as though it were declared once.
Then it starts the step-by-step execution of the code. In that step-by-step execution, any initializer on a var statement (the = 5 in var a = 5) is considered an assignment. So var a = 5 is treated exactly like a = 5 at this point.
So in your example:
var a = 5;
var a = undefined;
console.log(a); // undefined
a = 6;
It's as though you had written this:
var a = 5;
a = undefined;
console.log(a); // undefined
a = 6;
or this:
a = 5;
var a = undefined;
console.log(a); // undefined
a = 6;
or this:
a = 5;
a = undefined;
console.log(a); // undefined
var a = 6;
or this:
var a;
a = 5;
a = undefined;
console.log(a); // undefined
a = 6;
or this:
a = 5;
a = undefined;
console.log(a); // undefined
a = 6;
var a;
or even this (but please don't! :-) ):
var a = 5;
var a = undefined;
console.log(a); // undefined
var a = 6;
var a;
That is, first all the variables declared with var are created (and only once), then the code runs as though any initializers on them were assignments.
This is not how let, const, and class declarations are handled (collectively: lexically-scoped declarations). First: Multiple declarations in the same scope are an error (including if one of them is with var and the other is with one of the lexically-scoped ones). Second: They're hoisted (in Step 1 above), but the hoisted binding¹ is uninitialized until the declaration is executed in the step-by-step code, at which point it's initialized (either with the value from the initializer, or with undefined if it's just e.g. let a;). The time between entry to the scope and the point the binding is initialized is called the Temporal Dead Zone. var doesn't have it because var variables are initialized when they're created (with the value undefined), but let, const, and class declarations do.
¹ The term binding is the general term for variable-like things. In the code:
function example(p) {
var v;
let l;
const c = 42;
function f() {
}
class C {}
}
the bindings created upon entering the example function's scope are p (a parameter), v (a var variable), l (a let variable), c (a const constant), f (the binding created by a function declaration), and C (the binding created by a class declaration). (Note: function and class expressions are handled slightly differently.)
I am learning JavaScript. I wrote a simple code snippet:
var a=5;
var a=7;
console.log(a);
This outputs 7 and understandably so. However:
var b=2;
var b; //!=undefined?
console.log(b);
outputs 2. I was expecting undefined since variables are initialized to undefined on initialization. What am I missing?
Thanks!
Because of hoisting. Your code will be interpreted by browser like:
var b;
var b;
b = 2;
console.log(b);
For more information: https://www.w3schools.com/js/js_hoisting.asp
var initializations are hoisted, and duplicate initializations are ignored. Variable assignments are not hoisted. So, to the interpreter, your first code looks more like:
var a;
a = 5;
a = 7;
console.log(a);
and your second code looks like:
var b;
b = 2;
Just a plain "var b" is effectively ignored if b has already been declared as a var earlier.
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.
var myName = 4;
function myName() {
console.log("xxxx");
}
console.log(typeof myName); //Number
var myNamex;
function myNamex() {
console.log("xxxx");
}
console.log(typeof myNamex); //function
Please refer the fiddle - http://jsfiddle.net/s8a7m1hk/
console.log(typeof myName);
The above log statement logs different value, the only difference is that the variable is assigned a value in one place, and not in another.
Can you tell me how are both code snippet broken down, considering hoisting, closure or any that can be applied.
Your problem is very simple, once you have the hoisting in the right order. Effectively your code looks like this:
function myName() {
console.log("xxxx");
}
function myNamex() {
console.log("xxxx");
}
var myName;
var myNamex;
myName= 4;
console.log(typeof myName); //Number
console.log(typeof myNamex); //function
All the declarations (var statements and function declarations) are hoisted to the top. The assignment of the value 4 is not hoisted, so takes place after the declarations, so myName is 4 when it's logged. You never assign any other value to myNamex, so it is not changed and is still the function.
The spec will tell you the precise algorithm. Below, context is the [[Scope]] of the enclosing LexicalEnvironment, or the global object.
This is roughly what happens:
context.myName = function myName() { ... }; // From evaluating 1st function statement.
context.myNamex = function myNamex() { ... }; // From evaluating 2nd function statement.
context.myName; // From evaluating var declaration statement myName. Does nothing because property already exists.
context.myNamex; // From evaluating var declaration statement myNamex. Does nothing because property already exists.
context.myName = 4; // Changes the existing property to point to the number instead of the function myName.
console.log(typeof myName); // Number - for reasons that should now be clear.
console.log(typeof myNamex); // function - for reasons that should now be clear.
If I know the variable will be object later, I use:
var obj;
but it doesn't really matter if I initialize it as null or undefined:
var obj = null;
or
var obj = undefined;
For strings I personally use:
var str = '';
as later on I can do
str += 'some text';
and if I use null for example I get "nullsome text".
null, undefined, empty string or 0 are all falsy values so to check if they are defined. which is the correct way to initialize variables if my variable will be used as object, dom node, etc.. ?
It's initialized to undefined by default, just use that, you don't have to write it out:
var obj;
If it you want to concatenate to a string, use '', for counters use 0... Just use common sense.
In an ideal scenario, you'd just declare your variables at the top of the scope like so:
var foo, bar, obj, domNode;
All of these variables will be undefined, as in their value is undefined. If you know for a fact one of these variables will be used as a string in a loop, for example, rather thant writing foo = (foo === undefined ? '' : foo) + 'add this';, just write:
var foo = '', bar, obj, domNode;
If you're going to use the obj var as an object literal, just assign it {my: 'objec', vals: 'here'} when the time comes, or initialize it to {}, and add properties obj.as = 'you'; obj[foo] = 'go';. If you're going to assign a reference to a DOM element, keep it undefined, as any assignment will just generate pointless overhead.
Same goes for any type of reference (function objects, arrays, objects...). Just postpone the assignment, because it'll just overwrite any previous assignment.
As for numbers, undefined + 123 will get evaluate to NaN, so in that case, initializing to 0 makes sense. However, in case of loop counters:
var foo, i, obj, arr = [1,2,3];
for (i=0;i<arr.length;i++)
{
console.log(arr[i]);
}
is equivalent to:
var foo, i= 0, arr = [1,2,3];
for (;i<arr.length;i++)
{
console.log(arr[i]);
}
Only the latter almost looks wantonly complicated. Just use your common sense and you'll be all right.
Just know that variable declarations are hoisted to the top of the scope, but assignments aren't:
console.log(foo);//undefined
var foo = 123;
console.log(foo);//123
because it's translated into:
var foo;
console.log(foo);
foo = 123;
console.log(foo);
So why not write your code as it'll be interpreted by the engine?