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.
Related
This question already has answers here:
Using the variable "name" doesn't work with a JS object
(4 answers)
Closed 3 years ago.
I'm new to JavaScript and am trying to understand the concepts of hoisting and scope.
Case 1
var name;
function logName(num) {
console.log(name, num);
}
logName(1);
name = "Auro";
logName(2);
and I have the following output in the console
Auro 1
Auro 2
If I understand hoisting correctly, JS engine hoists the declaration of a variable first and then automatically assigns a value undefined to it. Only when it encounters the assignment (=) operator, does it actually assign the intended value to it.
If my understanding above is correct, then the first time the logName function was called, the variable name should have printed undefined, but it is printing the value.
Case 2
var name;
function logName(num) {
console.log(name, num);
}
logName(1);
name = "Auro";
logName(2);
name = "Baner";
Output in the console:
Baner 1
Auro 2
This confuses me even more. Here the first call to the function logName picked the later assignment to the variable and printed Baner, however, the second call picked the previous assignment, that is Auro.
What is going on here? What am I missing?
In the global scope, name refers to window.name, that is the name property of the window - which in the examples you gave are sif1 and sif2 (possibly "Snippet IFrame 1/2").
Since window.name already exists, var name; in the global scope does nothing. The variable is already defined.
Until you overwrite it - and note that again you are setting the global window.name property. And, depending on browser settings, this can persist across reloads of the page (since you're naming the entire window). This explains why you see the value "stick".
No none of the specified output matches, as initially you have value of name equal to window.name, so initially the value of name variable will be equal to winow.name and once overwrite it you get the new value
let's understand how this all works
You can understand as such there are two phase of code execution
Creation phase
Execution phase
Creation phase:- During creation phase function is hoisted at top as it is, while the variable are hoisted but there is no value assigned to it ( or you can say it's value is undefined )
Execution phase:- During execution context it assigns value to variable when it reaches line where assignment is happening
var name;
function logName(num) {
console.log(name, num);
}
logName(1);
name = "Auro";
logName(2);
name = "Baner";
As addition to other answers I can say, that just not use var but use ES6 let or const instead and 'surprising behaviour' will disappear.
let name;
function logName(num) {
console.log(name, num);
}
logName(1);
name = "Auro";
logName(2);
name = "Baner";
Why is the declaration of the variable 'a' not used in the output of the console log of the below code? Doesn't that go against the scope chain? The variable 'a' with the undefined value on line 4 surely should be used on the console output on line 5?
var a = 15;
function checkScope(a) {
var a;
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
I want to understand this behaviour. To confirm, this behaviour has nothing to do with hoisting or even scope (i.e. scope chain)?
I don't believe scope is relevant to explain this behaviour because 'a' exists locally (its value is 'undefined' as it's not initialised) within the function, hence the Javascript engine will not look to the outer lexical environment to find 'a' (which has a value of 15). Or as per the MDN page: "The scope of a variable declared with var is its current execution context", which in this case is the enclosing function 'a'.
I also don't believe this behaviour is a result of hoisting as far as I know.
So, in addition, this is what is stated on the MDN page? "If you re-declare a JavaScript variable, it will not lose its value."?
Off-topic question but, what's the reason behind MDN's statement above? Is it simply related to memory management? There's no point to logical reason to allocate a new memory address every single time a variable is declared?
Now, going back to my question:
Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored? But I don't think so because both variable are declared in their own, separate execution contexts, so surely the variable 'a' in line 4 is being used/accessed? Because the scope chain would suggest that the closest local variable would be used (i.e. the local 'a' with a value of undefined), and in addition, I would best think that the MDN statement applies to only re-declared variables only within the same lexical environment, correct?
I am just trying to work out whether 'a' in line 4 is actually used when we refer to 'a' in line 5? Or is line 3 ignored, and thus line 5 will instead access (refer to) the 'a' in line 3 (i.e. checkScope's 'a' parameter)?
- The latter sort of implies the former
It makes sense if line 3 from the above code is simply ignored, because deleting it achieves the same result:
var a = 15;
function checkScope(a) {
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
Thanks.
You have declared a variable named a three times.
Once as a global on line 1: var a = 15;
Twice inside the function:
Once with a var statement on line 4: var a;
Once with an argument definition on line 3: function checkScope(a) {
The line 4 var has no effect. The variable is already declared.
Then you call checkScope(a); which passes the value of the global a (15) to the local a argument of checkScope. This is why it is 15 and not undefined.
Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored?
var a is basically ignored.
But I don't think so because both variable are declared in their own, separate execution contexts
This is where you are being tripped up by having three and not two declarations of a. It declares the variable defined by the function argument name.
If you redeclare a JavaScript variable, it will not lose its value.
take a look at this answer.
var a = 15;
function checkScope(a) {
var a; // this is equivalent to redeclaring the variable
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
Basically line 4
var a;
is where the compiler finds a redeclared variable of the function parameter. Because of the missing initializing, a keeps the value of the handed over value of the parameter a.
Consider 'a' to be different assigned variable for arguments in function and inside as a local variable.
function a != var a;
Now, some 'a' is called by console.log(a). Now, it will search for the default 'a' value if existing, i.e, 'a' of function. Even on manipulation of 'a',
function hoist(a) {
var a;
a*=2;
console.log(a);
}
hoist(10);
output: 20
This question already has answers here:
What is the (function() { } )() construct in JavaScript?
(28 answers)
Closed 6 years ago.
from MDN, just wondering why the () around the function, why the extra () after it, and why the var b inside the function doesn't replace the value of the first var b, given it doesn't use the keyword let, which would keep b local to that function, thanks
var a = 1;
var b = 2;
(function() {
var b = 3;
a += b;
})();
a; // 4
b; // 2
When you write var b inside a function, the var keyword makes it a local variable. So, var b inside the function is a local variable and var b at the top which is outside the function is in global scope. You can read more about scoping in MDN. Also, the () after the function is called immediate function invocation which means that the function is given a call soon after it is defined. Also, since a inside the function has no var before its declaration, it will take the global a which is 1 and add 3, local variable b's value it.
The function is simply called immediately. That’s what the last parentheses are for. The extra parentheses around the function declaration are because
function() {
var b = 3;
a += b;
}();
would create a syntax error as the function keyword would not be interpreted as an expression here.
and why the var b inside the function doesn't replace the value of the first var b, given it doesn't use the keyword let, which would keep b local to that function,
You may have heard that the special thing about let is that it is block-scoped. That’s true. But var has always been scoped to the function and since the second var b is inside its own function it’s scoped to that function and does not affect the b from the top scope here.
The template
(function(){})();
Is a template of an anonymous function.
To explain it, let's create a function x() that alerts 'hello':
function x() {
alert('hello');
}
To call x, we will:
x();
Now, it's clear that if we replace an object's name with it's value, the statememt will stay the same (take for example var k = 5; alert(k); alert(5) - the two alerts are the same because variable's name was replaced with it's value).
In our case, x's value is:
function () {
alert('hello');
}
So if we replace x with it's value in the statement x(); ->
(function () {
alert('hello');
})();
And that's the source of the syntax. The result of that will be an immediate call to the specified function. Of course, this syntax works also for functions with parameters and functions with return types.
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();
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() { }