Why this strange behavior? [duplicate] - javascript

This question already has answers here:
Why is my global variable shadowed before the local declaration?
(3 answers)
Closed 9 years ago.
I'm modifying a piece of code in 3 ways. In these 3 conditions in is behaving differently. Please describe how it's executing?
var a=1;
function myFunc(){
console.log(a);
console.log(a)
}
myFunc();
//Output is:
1
1
var a=1;
function myFunc(){
console.log(a);
var a=2;
console.log(a)
}
myFunc();
//Output is:
undefined
2
var a=1;
function myFunc(){
console.log(a);
var a=2;
console.log(a)
}
myFunc(a);
//Output is:
undefined
2
Why in 2nd case it's printing undefined? And in 3rd case I'm sending my global a as an argument, then also it's printing undefined.

That's because JavaScript moves var declarations to the top of the scope, so your code actually is:
var a = 1;
function myFunc(){
var a; // a is redeclared, but no value is assigned
console.log(a); // therefore it evaluates to undefined
a = 2; // now a = 2
console.log(a); // and then it logs to 2
}
myFunc();
This behaviour is called Variable Hoisting.
EDIT
As Beterraba said, in the third code it logs undefined because no argument was declared in the function's header:
var a = 1;
function myFunc(a) { // a is declared
console.log(a); // now a logs 1
var a = 2; // now a = 2
console.log(a);
}
myFunc(a);

The second case is printing undefined due to the way that JavaScript Execution context works. You might have come across the term hoisting.
To explain it in more details, when the second function is invoked, the interpreter will enter a process with two phases.
Creation stage
Creates the scope chain
Creates arguments, functions, variables, the so-called variable object
Determines the value of "this" keyword
Activation or code execution stage
interprets and executes the code
So when you callmyFunc() the JavaScript interpreter will create an execution context which you can think of as an object literal that looks like this:
myFuncExecutionContext = {
scopeChain: { ... },
variableObject: {
arguments: {
length: 0
},
a: undefined,
},
this: { ... }
}
You can see that the local a variable has an initial value of undefined. During the code execution stage, the interpreter will run the function line by line; So the first line it sees is the console.log(a);. The interpreter will look at the variableObject to see if there is variable with that name. If not it will use the scope chain and will try to locate it in the variable object of the outer scopes. Since, there is the a variable in the variable object, it will read it's value, which is undefined.
Then it will do to line 2 where it will assign a value to the local variable a; var a=2;. Then it will execute the last line - console.log(a) - which will print the value that we assigned earlier.
The same mechanism justifies why we can invoke a function before it's defined, as long as, we use a function declaration syntax.
someFunc(); // VALID
function someFunc(){ };
Whereas the following will cause an error:
someFunc(); // TypeError: undefined is not a function
var someFunc = function() { }

Related

Hoisting inside function having same variable name [duplicate]

This question already has answers here:
Variables with the same name, but the local scope variable isn't being used, why?
(4 answers)
Closed 3 years ago.
So I thought I understood hoisting in JavaScript until I saw something like this:
function hoist(a) {
console.log(a);
var a = 10;
}
hoist(5);
The code above outputs 5, not undefined!
As per my understanding, the function looks like this to the interpreter:
function hoist(a) {
var a; // This should overshadow the parameter 'a' and 'undefined' should be assigned to it
console.log(a); // so this should print undefined
a = 10; // now a is assigned 10
}
So what's happening here?
You would be right if the var was called b, but the var a already exists. redeclaring a javascript variable that already exists doesn't do anything. It will not change the value to undefined. Try it.
function hoist(a) {
var a; // no op, does not change a to undefined.
console.log(a);
a = 10;
}
hoist(18);
This falls back in the section Only declarations are hoisted in the MDN (to link some documentation, at least).
The second example given there is the exact one you're looking for:
num = 6;
console.log(num); // returns 6
var num; // or, really, var num = whatever.
To just recall what is said:
If you declare the variable after it is used, but initialize it beforehand, it will return the value.
Hoisting a variable means that the variable name is known to the compiler from the beginning of the block. It does not re-introduce, overwrite, clear or reset the variable if it already exists.
Until something is assigned, the value of that variable is undefined, but hoisting itself does nothing to the value of the variable.
It so happens that a function parameter is also a way of declaring a variable, like an invisible var statement, followed by an assignment that happens as the function gets called, before any of the actual function body executes.
Hoisting is still working as we expect, as we can see that the following snippet also outputs 5:
function hoist(a) {
var a;
console.log(a);
a = 10;
}
hoist(5);
What we really have here is a function parameter, a, being redeclared inside the function where its value has already been initialized to 5.
you are correct that hoisting would work this way inside of that function.
In this particular example we pass an argument/parameter to our function and it changes how it will be interpreted. Just take a look:
function hoist(a) { // here's our 'a' parameter gets replaced by '5' that we passed while execution of this function
var a; // with no new value it does nothing
console.log(a); // so this will print 5 that we passed to this function
a = 10; // now a is assigned 10 and next console.log() would show a new value of 'a' variable
}
Hoisting has to do with calling a function before it is declared, as javascript will push the function declarations to the top. The parameter a and the variable a don't related to hoisting in this case.

JavaScript hoisting for multiple declarations of the same variable

I was trying to understand JavaScript hoisting and from what I have understood, memory space is set aside for all the variable declarations before the execution of the code.
I would like to understand how the interpreter works through hoisting in case of multiple declarations for the same variable. Consider the following code:
console.log(a);
//first declaration
function a() {
console.log('hello');
}
//second declaration
var a = 2;
The output is the function declaration:
function a() {
console.log('hello');
}
So, I am assuming the first declaration the interpreter encounters is the one which is stored in memory. However, changing the order of declarations to:
console.log(a);
//first declaration
var a = 2;
//second declaration
function a() {
console.log('hello');
}
results in the same output! The interpreter ignores the first declaration and stores the second declaration in memory. Why is this happening? Shouldn't the output in the second case be undefined?
Your code will be read by the interpreter like below,
function a() {
console.log('hello');
}
var a;
console.log(a);
a = 2;
so while executing the above code, a will be referring the function initially and after that var a; line will be executed, since a is undefined there, an assigned value will not be set with undefined by means of a variable declaration. Hence that line got ignored and printing the primitive value of the function reference.
A simple example for your better understanding would be,
function x(){ };
var x;
console.log(x); //function x(){ }

Global variable override with a local one

The following test is a success, and prints 1 and 1:
function test1() {
a = 1;
console.log(a); // prints "1"
}
function test2() {
console.log(a); // prints "1"
}
test1();
test2();
And the following test fails, because a local variable overrides the previously created global one:
function test1() {
a = 1;
var a = 2;
console.log(a); // prints "2"
}
function test2() {
console.log(a); // throws an error
}
test1();
test2();
Why does the second example remove the global variable permanently? What purpose/logic does such functionality serve in JavaScript?
EDITED: For those who marked it as a duplicate of Strange Behavior on Global and Local Variable in JavaScript
Hoisting refers to the scenario when a later declared local variable is moved up the function scope, overriding the previously visible variable. But in our case the function first creates a global variable, and then deletes it completely/globally.
However, it is probably related, as we can see in the following test:
function test1() {
a = 1;
console.log(a); // prints "1"
}
function test2() {
console.log(a); // prints "undefined"
var a = 2;
}
function test3() {
console.log(a); // prints "1"
}
test1();
test2();
test3();
In your second case, no global variable named a ever exists.
a = 1 generally does not create a global variable. The statement a = 1 stores the value 1 in a variable called a. If the variable environment of any containing local scope has a variable called a, the nearest scope with an a variable will have that variable set to 1.
As a special case, if a variable called a does not exist in any containing scope (and if you are not in strict mode), then the JavaScript engine will create a global variable called a.
In your second case, var a creates an a variable in the local scope. Due to hoisting, that modification to the scope's variable environment happens before any code runs. Thus, by the time a = 1 is executed, that local scope does have a variable called a, so that local variable is used.
In your third case, test2 logs the local variable a (created by the var a). At the time the log call is made, the local a has not yet been assigned a value.
Hoisting refers to the scenario when a later declared local variable is moved up the function scope, overriding the previously visible variable.
Hoisting simply means that all var declarations are treated as if they happen at the top of their containing function. It has nothing to do (directly) with overriding variable visibility.
Note that declarations with an assignment will have only the declaration hoisted, not the assignment. The assignment stays in place wherever it is in the function.
Javascript moves variable declarations to the top. So in this example the compiler reads you code as:
function test1() {
var a;
a = 1;
a = 2;
console.log(a); // prints "2"
}
function test2() {
console.log(a); // throws an error
}
test1();
test2();

Global variable returned as undefined when it is again declared locally in a block and referred before the declaration in the block. [duplicate]

This question already has answers here:
Why does local variable kill my global variable?
(6 answers)
Closed 8 years ago.
var a = 10;
function example(){
alert(a);
var a = 5;
}
example();
This code alerts undefined.
My question is why variable a is alerting "undefined" instead of returning global variable's value.
My thanks to everyone in advance. I hope someone will clarify it for me.
Inside Javascript functions each declaration of variable is always hoisted to the top of it, but not assignment of its value. What you're really executing is:
var a = 10;
function example(){
var a; //undefined!
alert(a); //still undefined!
a = 5; //only now it becomes 5
}
example();
Read more about hoisting in Javascript: Javascript hoisting explained
To avoid declaring new, local variable, and instead just use already defined global one:
var a = 10;
function example(){
alert(a);
a = 5;
}
example();
This looks like what you're trying to achieve here.
Because of hoisting of variable a. The below is what is happening. The a inside the function is getting hoisted to the top of the function body, and it shadows the a which is outside the function and has the value of 10.
And you're alerting a before it was initialized, in the case of which, a will have the default value of undefined.
var a = 10;
function example(){
var a; // this is undefined and shadows the global a
alert(a);
a = 5;
alert(a); // 5
}
example();
This happens because, If you declare a global variable and a local variable with the same name, the local variable will have priority when you attempt to use the variable inside a function. That being said, since you try to alert the value of a and you have defined a local variable with the same name in your function scope, in the alert the value of the local variable would be appear. However, you declare the variable after the alert statement. Hence it's value is undefined.
If you try to run the following snippet, in which we have removed the declaration of another variable with name a, you will get the expected behavior.
var a = 10;
function example(){
alert(a);
a = 5;
}
example();

when should I put var in front of function in js?

<script type="text/javascript">
var output = function() {console.log('result')}
output();
</script>
If I changed to output = function() {console.log('result')}; it still shows the right result, so my question is:
what is the difference between them? when should I put var in front of function in js? is that the same principle as var in front of variable?
A function defined in a script tag is in the global scope (ie the window object in a browser context) so there is no difference in this case.
Inside a function block, however, is a different story. For example:
foo = function() {
var foo = 1;
console.log(foo);
}
foo(); // logs '1'
foo(); // logs '1'
But:
foo = function() {
foo = 1;
console.log(foo);
}
foo(); // logs '1'
foo(); // SyntaxError: Unexpected token function
Because foo wasn't defined locally, we overwrote the global object.
You're in the global window scope, so there's no difference.
It doesn't matter what the type of the variable is.
If this is declared in functions, then there is a difference:
function name(){
var a=1;
}
alert(a);
Here a will be undefined, as var declares the variable in the scope of the function.
As an excercise:
var a=2;
function name(){
var a=1;
}
name();
alert(a);
This alerts 2 instead of 1, since the middle var belongs in the scope of the function, which is separate from the global scope.
You can also modify global variables this way:
var a=2;
function name(){
a=3;
}
name();
alert(a);
Also compare this with let, which limits it's scope to the block instead: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
"Is that the same principle as var in front of variable?"
Yes. output is a variable.
So I would suggest you use var in front of it when you define it. You could eventually change its value without using var. As in:
var A=1;
A=2;
A=A+1;
Consider the "script" of the funcion as the "value" of that variable.
var F=function() {console.log('one')};
// change it later
F=function() {console.log('two')};
(not suggesting you do this, but to show you it is 100% a var)
You are actually assigning to the variable named "output" a value of "function() {console.log('result')}" not as a string but as a script that gets executed. Note the semicolon at the end like in var A=3;
Now "inside" output there is the code that executes console.log('result'). (more or less, just to explain).
As you usually do not change that same function later (you can, and sometimes it is done) I really suggest you use var in front of it every time you define a function like this, even in cases when it is not strictly necessary, just to be safe you do not override an existing function.
This is a bit different from defining the function as:
function output() {console.log('result')}
Here there is no = sign, no assignment, no semicolon at the end. This is not a variable assignment but a function "definition" although results are similar, and you can call output() in both cases, there are differences. The main one I think is that function definitions are examined before executing the script line by line, while with assignment you really need to have the assignment line processed before you can use the function. So this:
output();
function output() {console.log('result')}
works. While this:
output(); // nope! output not defined yet!
var output=function() {console.log('result')}
doesn't. Variables are assigned or changed when the assignment instruction is read and interpreted.
// here A is undefined, B() prints 'ok'
var A=function() {console.log('first')};
// here A() prints 'first', B() prints 'ok' as usual
A=function() {console.log('second')}; // change it
// here A() prints 'second', B() prints 'ok' as usual
function B() {console.log('ok')}
// same here A() prints 'second', B() prints 'ok'
Without var your variable will be declared as global variable which means it is available on other JS files too. In short If you declare a variable, without using var, the variable always becomes GLOBAL.
Generally there is no difference because you are in the global scope, but in ES5 there's a strict mode, which slightly changes the behavior of undeclared variables. In strict mode, assignment to an undeclared identifier (not putting var in front) is a ReferenceError.
For example:
"use strict";
myVariable = "foo"; // throws a ReferenceError
Function or not function, here's what MDN has to say about var:
The scope of a variable declared with var is the enclosing function or, for variables declared outside a function, the global scope (which is bound to the global object).
Using var outside a function is optional; assigning a value to an undeclared variable implicitly declares it as a global variable (it is now a property of the global object). The difference is that a declared variable is a non-configurable property of the global object while an undeclared is configurable.
And you could also read about the function statement here and the function operator here.
Cheers!

Categories

Resources