to all javascript gurus out there: why does this happen? - javascript

Why does this code:
function answer(x) {
function closure() {
var x = x || 42;
console.log(x);
}
closure();
}
foo();
always prints 42?
The logic would be that something like foo(31337) would print 31337, since in closure x would be 31337, so x || 42 would evaluate to 31337. But this is not the case.
I just can't figure this out, so I'm posting this here in hope of receiving enlightenment from one of the true javascript gurus out there.

function answer(x) {
function closure() {
var x = x || 42;
console.log(x);
}
closure();
}
answer(20);
inside closure your defining x as a local variable. This means it shadows the argument x from the answer function higher up the chain. Since you declared x with a var statement it defaults to undefined.
Then x || 42 is undefined || 42 which is 42.
The issue here is that your using the same name. If you did x = x || 42 it would be x = 28 || 42 which sets x to 28.
The distinction is using the var statement to create a new function local variable named x. Once you've done that, there is no way to reference variables of the same name that are higher up the scope chain.
To clarify how the interpreter works. Something like this :
function() {
var x = 52;
foo();
function foo() {
...
}
}
Gets converted into
function() {
function foo() {
}
var x;
x = 52;
foo();
}

var x in var x = x || 42; shadows the argument.
And since var ... is always parsed at the beginning of the function - i.e. before the assignment is executed, the outer x is never available in there.
Here's a better example:
(function(x) {
(function() {
alert(x);
var x = 'inside';
})();
})(123);
The execution order is basically:
Define var x with value undefined
Execute alert(x)
Assign 'inside' to x

Related

Javascript scope issues with Revealing Module Pattern

One more JavaScript scoping problem. I believe this is not related to 'hoisting'.
I've a small block of code here - http://jsfiddle.net/0oqLzsec/2/
var c = function(){
var x = 'before',
callBefore = function(){
alert(x);
},
callAfter = function(){
_callAfter();
};
return{
callBefore : callBefore,
callAfter : callAfter
}
var y = 'after';
function _callAfter(){
alert(y);
}
};
var obj = c();
obj.callBefore();
obj.callAfter();
callAfter() always alerts 'undefined' even if the variable y is defined before _callAfter(). But If I move the variable y declaration before variable x it is working.
I'm wondering if callAfter() can _callAfter() which is defined below, why can't it read variable y?
_callAfter and y are both hoisted, which makes them known as local variables through the function invocation. The _callAfter function is able to be called (as you do), and it also closes over the variable y. However, this variable does not get a value assigned before you return from the c function. Thus, you get undefined. It is the same if you put var y; BEFORE the return, and y='after'; after the return.
In other words, the following two are equivalent:
function foo(){
var a;
return function(){ return a };
a = 42; // never runs
}
alert( foo()() );
function bar(){
return function(){ return a };
var a = 42;
}
alert( bar()() );
Here's an example showing that the local variable is hoisted and closed over, even when the function literal occurs before the var in code:
function build() {
return function(newValue) {
alert("was: " + oldValue);
oldValue = newValue;
alert("now: " + oldValue);
}
var oldValue = 42;
}
f = build();
f(17);
// was: undefined
// now: 17
f(99);
// was: 17
// now: 99
It is related to hoisting, var y is moved to the top of the function, but the assignment (y = 'after') is not, so it never runs because it's after the return statement.
The JS engine rewrites your code to look something like:
var c = function(){
// functions also get hoisted to the top
function _callAfter(){
alert(y);
}
var x = 'before',
callBefore = function(){
alert(x);
},
callAfter = function(){
_callAfter();
},
// y declaration is hoisted to the top of the function
y;
return {
callBefore : callBefore,
callAfter : callAfter
};
// the assignment never gets called because it's after the return
y = 'after';
};

Variable hoisting - "var" with global variable name in function

I was practicing some scenario and find a case:
Here is fiddle
According to closure bar function should have access to var x so I expected to alert 1 and condition get false due to if(!1) but it alerted undefined and condition get true and second alert is with value 10.
var x = 1;
function bar() {
alert(x);
if (!x) {
var x = 10;
}
alert(x);
}
bar();
So I am confused why it is prompting undefined?
According to hoisting in a particular scope you define a variable anywhere it is considered as defined at top always.
If it is due to hoisting effect it still have to alert 10 instead of undefined.
Hoisting causes a variable to be declared everywhere in the function, not defined.
On the first line of bar, since there is var x on line 3 of the function, the global x is masked and you see the local x (which is undefined since it hasn't been given a value yet).
On line 3 of bar, you have x = 10 which defines the variable. This is not hoisted.
On line 5, you alert it, and it is now defined.
Hoisting will make your code effectively work like this:
var x;
x = 1;
function bar() {
var x; //same as var x = undefined;
alert(x);
if (!x) {
x = 10;
}
alert(x);
}
bar();

Does assigning a function to a variable in javascript run the function

I have three simple programs below with different outputs. I am a bit confused as to why I get a different output. What really happens when you assign a function to a variable? Does it not run unless you have parentheses (i.e. myfunction())? I'm also very confused as to how JavaScript allows the parenthesis behind a function as 'optional' when calling it. Can someone clear this up? I only know Java so this is all new territory for me.
// ------First--------------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction;
w();
console.log(x);
//output is 3
// ---------Second -----------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction;
console.log(x);
//output is 9
// ---------Third -----------------------------
var x = 9;
function myfunction (){
x = 3;
}
var w = myfunction();
console.log(x);
//output is 3
No, it does not. A reference to a function by name is simply a reference to a value, like any other value. Without the () operator, it's not a function call.
Parentheses are not optional when calling a function except when it's being called via the new operator. Thus:
function foo() {
console.log("hi!");
}
var otherFoo = foo; // no function call
var obj = new foo; // function call via "new"
var x = foo(); // function call via "()"

JavaScript block scope vs function

Are following snippets exactly equal? If no what is the deference?
var x = (function() {
... //a
return function(){
... //b
};
})();
vs.
var x;
{
... //a
x = function(){
... //b
};
}
There is a major difference: In JavaScript, blocks don't induce a new variable scope. Therefore, you can't define private variables in the // a code block. Compare
var x = (function() {
var v = 42;
return function(){
return v;
};
})();
// v; would yield ReferenceError: v is not defined, so you need to call x
and
var x;
{
var v = 42;
x = function(){
return v;
};
}
// v is 42 here, that's not what's intended.
One major difference is that at the time of executing ...//a , x doesn't exist. Now in your case, in both cases it is undefined but generally speaking it's possible to access x variable during ...//a while in the first case it's not.
Otherwise in your circumstances it's pretty same. After all in your case the code is basically refactored into a separate function just like in any other language.

Javascript Evaluation Questions (Part 2)

(function () {
var x = 5;
(function () {
function f(y) { return (x+y)-2 };
(function () {
function g(h) { var x = 7; return h(x) };
(function () { var x=10; z=g(f); })();
})();
})();
})();
I'm working through some problems from my textbook in my class to prepare for our next exam, and can't figure out how the above evaluates.
Mostly, I don't understand the call z=g(f), as when f is evaluated, it isn't provided an argument, so how does it evaluate at all? How does it know what y is? What would g(f) evaluate to?
Also, as far as scoping goes, I believe javascript treats most everything as global variables, so the last x that is set would be the x value used in function f, correct?
Thanks for any help!
Please note, these are extra problems in the back of the book I'm practicing to prepare for the exam, these are not direct homework questions.
In this case of g(f) the function f is not evaluated but instead is passed as an object / value. Functions are values in javascript and can be passed as such. The function g later evaluates the function f via the expression h(x) (because f is passed as the parameter h)
Here's a more direct example
var addOne = function(x) { return x+1; }
var f = addOne;
var value = f(4); // Returns 5
It helps to have better formatting and indentation so that it's easier to investigate what's happening:
(function() {
var x = 5;
(function() {
function f(y) { // <-- y is the x from function g
return (x + y) - 2
};
(function() {
function g(h) {
var x = 7; // <-- local x is defined and passed to f
return h(x) // <-- h === f
};
(function() {
var x = 10;
z = g(f); // <-- f is passed to g
})()
})()
})()
})()
Variables defined within functions are scoped to that function. You should probably figure out the rest from there if this is really for a class.
Mostly, I don't understand the call
z=g(f), as when f is evaluated, it
isn't provided an argument, so how
does it evaluate at all? How does it
know what y is? What would g(f)
evaluate to?
If you look at how g is implemented:
function g(h) { var x = 7; return h(x) };
It takes an argument h, which is a Function, and then calls it as h(x). I hope this helps you understand how z = g(f) ends up running function f.
Also, as far as scoping goes, I
believe javascript treats most
everything as global variables, so the
last x that is set would be the x
value used in function f, correct?
Incorrect. When the var statement is used, a new variable in the local scope is defined. In your case, the final x is not global.
I also beautified it for readability.
(function () {
var x = 5;
This sets a local variable x to 5.
(function () {
function f(y) {
return (x + y) - 2
};
This creates a local function f; note that the above x (currently 5) is closed in.
(function () {
function g(h) {
var x = 7;
return h(x)
};
We define a function g that takes a function h as a parameter. It has a local variable x, which shadows the other one.
(function () {
var x = 10;
z = g(f);
})()
This x is a red herring; it shadows the outer one, and is never actually used. We then call g, passing f. Going above to g, we see that f becomes formal parameter h, and is called with 7. In f, that becomes y. So we get (5 + 7) - 2, 10. Due to the shadowing, it is not equivalent to the other code.
The outer x is never modified, just shadowed.

Categories

Resources