Why does this alert 5? - javascript

Curious bit of code here...
var x = 5;
function fn() {
x = 10;
return;
function x() {}
}
fn();
alert(x);
Here's the jsFiddle
Is function x() {} called at all after return ?
Why not alert 10?

function x() {} is hoisted to the start of fn's scope, and this effectively makes x a local variable before x = 10; is evaluated.
The function is not set to 10.
Update: The sentence above is wrong. x is actually set to 10. var is not used to declare it, but even if it was, the last sentence in the quote below only refers to the declaration part of the name x, not its assignment to 10.
From MDN (emphasis mine):
function
Three forms with different scope behavior:
declared:
as a statement at the parent function top-level
behaves like a var binding that gets initialized to that function
initialization "hoists" to the very top of the parent function, above vars
var
function-scoped
hoist to the top of its function
redeclarations of the same name in the same scope are no-ops

function x float to the top, so you assigning the function to 10

You are declaring function x within fn; therefore, you are using the locally scoped version of x. It doesn't matter at what point the function x is declared. What you are actually doing when you set x to 10 is you are setting the function of x to 10.

This code also alerts 5:
var x = 5;
function fn() {
x = 10;
return;
var x;
}
fn();
alert(x);​
The important point is that you are declaring a local variable x. Declaring a variable after the return statement also doesn't matter - it is still a local variable.
Remove the declaration and you get 10 instead because the x is no longer a local variable.

This is caused by the way variable hoisting works in JavaScript. Variable declarations are hoisted but not their assignemnts. Function declarations are also hoisted together with the function body (although function expressions are not).
So your code is effectively doing this:
var x = 5;
function fn() {
var x;
x = function () {}
x = 10;
return;
}
fn();
alert(x);
The x within the function is hence declared with only local scope and does not affect the x decalred in the main code.

This is because fn is an object, and x is a property of that object. Local-scope always takes precisence over globals.

X in fn() is a function
but x in the global scope is a var
remove the function x() {} part and x will be alerted 10

Related

Function inside a function for scoping

I am confused about this code how is this working although it looks simple but i am not getting the point of its working
<script>
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2));
console.log(add10(2));
</script>
Try to understand how closure works in JavaScript, then you will be able to understand.
Closure can simply be defined as "In JavaScript, the inner function has the access to all the variables defined outside of that functions."
Try understanding the concepts before trying to understand the code.
the function makeAdder returns a function that already will have "x" set with what ever you passed into "makeAdder"
<script>
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
//at this point "add5" looks like this:
/*
function add5(y){
return 5 + y;
}
so if we do: add5(2) - we know why we see the result we do
*/
console.log(add5(2));
</script>
It's called Closure
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
If you refer a variable in a function, it first checks that variable in its scope (inside that function) and if not found, it looks into that the environment where is was defined/declared.
So when you call your outer function with some parameter, it returns a new function. Inner function on invocation return sum of x a variable in parent scope when it (function) was defined and y the parameter passed to innner function. So inner function will keep remember the value of x when it was defined.
e.g.
var add5 = makeAdder(5);
Now add5 is a funtion which when initialized, value of x in it's parent scope was 5, so whenever you will call add5(4), it will do x + y where x = 5 value when retruned function was defined and y = 4 the value passed to add5 function or returned function.
I hope that will explain but I would suggest to read more about Javascript Closures. I added one reference above.

In JavaScript, why does this global variable become undefined in my function? [duplicate]

This question already has answers here:
Can you clarify this JavaScript variable hoisting behavior?
(3 answers)
Closed 5 years ago.
var x = 3;
function func(randomize) {
if (randomize) {
var x = Math.random();
return x;
}
return x;
}
console.log(func(false));
As you can see from above code, if statement never be true but the x value is undefined, i would like to understand how variable declaration works in javascript. Any references also be helpful.
Update:
Can anybody explain why variable was re-declared to undefined and how it is related to hoisting in javascript
Because func is in essence:
function func(randomize) {
var x;
if (randomize) {
x = Math.random();
return x;
}
return x;
}
Variables in JavaScript have function scope, not block scope with which you might be familiar from other languages. This results in the hoisting behavior you observe:
What does happen is that variable and function declarations are put into memory during the compile phase, but stays exactly where you typed it in your coding.
...
JavaScript only hoists declarations, not initializations. (emphases mine)
That is, even though inside func you declare x in the if block, during compile time its declaration is moved to function level where it shadows x in global scope. However, it is only initialized if the argument to func is true which leads to the behavior you observe.
See also let:
"use strict";
var x = 3;
function func(randomize) {
if (randomize) {
let x = Math.random();
return x;
}
return x;
}
console.log(func(false));
console.log(func(true));
You define a new variable var x in your function and thus overwrite the outer variable x.

Javascript Hoisting/Scope

I'm learning Javascript at the minute and have a question about hoisting/scoping - perhaps I'm missing something.
If I define a global variable, I cant reference that variable's value inside a function because its out of scope?
var x = "hello";
function temp(){
console.log(x);
}
turns out to be
var x = "hello";
function temp(){
var x;
console.log(x);
}
which both outputs undefined. What are the points of global variables or how do you use them inside a function? - As I said what am i missing here! :)
Also hoisting works on functions? But NOT on anonymous functions? Correct?
Any help is appreciated!
Thanks!
Hoisting only applies to local variables (those declared with var in the current scope). Since there's no var in temp(), there's no hoisting.
Here x will be hoisted:
var x = "hello";
function temp(){
console.log(x); // undefined
var x = 55
}
temp()
because this is interpreted as:
var x = "hello";
function temp(){
var x /* = undefined */
console.log(x);
x = 55
}
temp()
You can access any variable that is defined in your scope or higher. If that same variable name is redeclared within your scope, then that becomes a new variable definition that overrides the other one.
So, with this example:
var x = "hello";
function temp(){
console.log(x); // outputs "hello" when temp() is called
}
x is defined at a higher scope than the function so it can be used inside the function.
In this example:
var x = "hello";
function temp(){
var x;
console.log(x); // outputs "undefined" when temp() is called
// because local var x has not been assigned a value
}
You've defined a new variable x which is a local variable inside the function and it's value will be undefined until you assign it something.
The term "hoisting" means that a variable defined anywhere within a scope (e.g. within a function) behaves as if it was defined at the very beginning of the function no matter where the declaration actually appears.
So, because of hoisting, this example:
var x = 10;
function temp() {
x = 3;
y = 4;
var x;
console.log(x);
}
behaves like this and all references to x within the function are to the local version of x:
var x = 10;
function temp() {
var x;
x = 3;
y = 4;
console.log(x);
}

Javascript variable declarations at the head of a function

I've been told that javascript variables should all come before they are used in a function, such that:
function contrived() {
var myA, myB;
myA = 10;
myB = 20;
return myA + myB;
}
Is prefered over:
function furtherContrivance() {
var myA = 10;
var myB = 20;
return myA + myB;
}
Is this the case? And why is that?
I guess some people might prefer the former style because that's how it works inside. All local variables exist for the entire lifetime of the function, even if you use var to declare them in the middle of the function.
There's nothing wrong with declaring variables later in the function, syntax-wise, it might just be confusing as the variables will then exist before the line that declares them. Hence this function:
function bar() {
alert(foo); // Alerts "undefined". Not an error because the variable does exist.
var foo = 10;
alert(foo); // Alerts the value 10.
}
Is equivalent to this:
function bar() {
var foo;
alert(foo);
foo = 10;
alert(foo);
}
Another related fact is that nested function definitions (done using function foo() { ... }) will get moved to the top of the containing function as well, so they will be available even if the code that calls them comes before them.
Yes, the variable declaration should come at the top of the function:
function foo() {
var a, b;
}
However, initializing variables can be part of the declaration:
function foo() {
var a = 10, b = 20;
}
The reasoning behind declaring all variables at the top of the function where they are used is to avoid scope confusion.
Here is an example of bad code:
function foo() {
var b;
for (var i = 0; i < 5; i++) {
var a;
a = b = i;
setTimeout(function(){
console.log(a, b);
}, 1000);
}
}
If you execute the code, it will log 4, 4 5 times, rather than counting up. This is because only functions act as closures and introduce new scope. In JavaScript, any var declaration within a function gets executed at the beginning of the function.
This makes the above error much more visible:
function foo() {
var a, b, i;
for (i = 0; i < 5; i++) {
a = b = i;
setTimeout(function(){
console.log(a, b);
}, 1000);
}
}
There is no difference in this case between this two. I'd go with:
function furtherContrivance() {
var myA = 10,
myB = 20;
return myA + myB;
}
which is knows as single var pattern in javascript.
What you really need to take care of is defining your variables in the beginning of your functions. There is a thing in javascript called variables hoisting which means that variable definitions used in function "raise" on top. It's best described by an example:
var x = 'global'; // global (bounded to a global object which is window in browsers)
function func() {
alert(x); // undefined (you expected 'global', right?)
var x = 'local';
alert(x); // local
}
func();
what really happens is called (as I said) variables hoisting (definition of x raises on top), so the code above is actually the same as:
var x = 'global';
function func() {
var x; // definition of `x` raised on top (variables hoisting)
alert(x); // undefined in a local scope
x = 'local';
alert(x);
}
What a javscript interpreter does is it looks inside a function, gathers locally defined variables and raises them on top - this might be a good reason why you should use single var pattern.
In the example you give this is absolutely not the case. In a language like Javascript, it will be more of a developer preference, but it won't have any impact on the result.
Yes, place them at the top. It adds to code clarity.
Try this example:
var x = 1;
(function() {
x++;
alert( x ); // What will this alert show?
var x = 'done';
alert( x );
})();
Looks like it should alert 2, but it alerts NaN.
This is because the variable declaration is hoisted to the top, but the initialization stays in the same place.
So what is actually happening is:
var x = 1;
(function() {
var x;
x++;
alert( x ); // What will this alert show? NaN
x = 'done';
alert( x );
})();
...which makes the NaN expected.
For readability, it's definitely preferred.
However, Javascript "hoists" declarations. Hoisting means that vars and functions will be automatically moved to the top of their scope. This allows you to do things such as use a function before it's declared:
function myScope()
{
test();
function test()
{
//...
}
}
This can lead to some confusion, especially if variables within block scopes are declared. For example:
for(var i in foo)
{
var e = myFunc();
}
The declaration of e will be hoisted to the top of the closure, and e will be initialized to undefined. This allows for some interesting non-intuitive situations, such as:
if(!foo) //Will not throw reference error because foo is declared already
{
var foo = {};
}
So, regardless of how you declare your variables, they'll all get "moved up" to the top of the function anyway.
Hope this helps!

Why is the variable inside this function global?

I thought any variable defined in a function would be local but I can easily access variable 'e' outside of its function.
function change() {
var d = 6;
e = 7;
}
change();
alert(e); //> alerts 7
Because new variables will enter the global scope by default. var prevents this from happening by constraining a variable's existence to be within the current scope.
Because it was declared without var it becomes part of the global window object.
You've not explicitly declared it as such, so it has taken global scope.
Thats because e is global by default, using var make a scope varible.
You can read more about this in Javascript Garden Scope and Namespaces
I am guessing that you are going under this assumption that
JSLint expects that a var will be
declared only once, and that it will
be declared before it is used.
Problem with your code is you are using one var, but your second line has no var in front of it. That is pushing that varaible e into the global namespace.
Why is it happening? You used a semicolon instead of a comma in the variable declaration.
function change() {
var d = 6, //Change this to a comma
e = 7;
}
change();
alert(e); //will produce an error now
It is surprisingly easy to create global variables, here are some other gotchas I've seen.
// :-( antipattern: implied global variable
function sum(x, y) {
result = x + y; // result is global
return result;
}
// :-) better
function sum(x, y) {
var result = x + y; // result is local
return result;
}
// :-( antipattern: chain assignments as part of a var declaration
function foo() {
var a = b = 0; // b is global
}
// :-) better
function foo() {
var a, b;
a = b = 0; // both local
}

Categories