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';
};
Related
I just tried to check the scope variation by using the following code, but the result is coming not in an expected way. Can anyone explain what's going on exactly behind this..?
var a = 10;
+ function () {
a = 5;
var a;
alert("inline " + a); //Expected undefined but it displayed as 5
}();
alert(a); //Expected 5 but it alerted 10
DEMO
var hoisting
Because variable declarations (and declarations in general) are
processed before any code is executed, declaring a variable anywhere
in the code is equivalent to declaring it at the top. This also means
that a variable can appear to be used before it's declare
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
The compiler understands your code as
var a;
a = 5;
The position of a var declaration within a function doesn't matter. These are entirely equivalent:
function () {
var a;
a = 5;
}
function () {
a = 5;
var a;
}
when use "var a" you request global value of variable, use "window.a" to display it:
<script>
var a = 10;
+ function () {
a = 5;
var a;
alert("inline " + window.a); //Expected undefined but it displayed as 5
}();
</script>
var a = 10; // Global scope
+ function () {
a = 5; // You are not using Var here .. so it is also a global scope
var a; // Now you are mentioning your a is Var so scope is changed from global to this function
alert("inline " + a); // Printing 5 because you local scope a has value of 5.
}();
alert(a); // Printing 10 because of global scope a has value 10
I have a self invoking function in javascript and I have another function in the same file where I need the value of a variable that is inside the self-invoking function. How can I do that?
Edit: So I can get one variable, but how about more variables or an array?
And I also have a semicolon at the beggining, how to deal with it:
;(function() {
...
})();
You need to set it as part of the return. Depending upon your exact pattern it could go like
var app =(function(){
var x = 5;
function app() {
}
app.x = x;
return app;
})();
Simple define the variable not in the function but before:
var a = 1;
(function(){ /* do stuff and use a*/})();
function(){
// use a again
}
var x = (function(y) { return y + 2; })(2);
alert(x);
Works just like this:
function addTwo(y) { return y + 2; }
x = addTwo(2);
//Your self invoking func
(function(){
var getStuff = holdsStuff();
console.log(getStuff.a); //getStuff.b, getStuff.cArr etc;
})();
//func in same file that holds the vars that you need.
function holdsStuff(){
var a = 10;
var b = 15;
var cArr = [1,2,3,4,5];
return { a: a, b: b, cArr: cArr};
}
Is there any way to create\return a pointer to variable in JavaScript ?
like, in PHP :
function func() {
.....
return &$result;
}
I have a JS function like:
function(...) {
x=document.getElements..... //x is HTML tag
if (x.localName=='input') return x.value //String variable
else if (x.localName=='textarea') return x.innerHTML //String variable
}
Using this function, I can get a copy of the data from x, but not to change the source.
I want possibility to change it too.
Thanks
No, you can't return a pointer to a string. In Javascript Objects are assigned and passed by reference automatically, and primitives are copied. So if you return x; then you can modify x.innerHTML, but if you return x.innerHTML the string will be copied.
Hej Dani-Br
you can do something like this
function(...) {
var x = document.getElements..... //x is HTML tag
if (x.localName=='input') return {
get: function() { return x.value },
set: function(v) { x.value = v; }
};
else if (x.localName=='textarea') return {
get: function() { return x.innerHTML },
set: function(v) { x.innerHTML = v; }
};
}
so that the caller can set and get the value.
ps. use var to declare local vars
GL
Primitive types are passed by value. Objects are passed by reference. I guess x.innerHTML is a string, so it is passed by value.
Take a look at this piece of code, it shows you passing objects by reference:
function test(str){
return str;
}
var k = { txt : 'foo' },
n = test(k);
console.log(n.txt);
k.txt = 'bar';
console.log(n.txt);
This might not be exactly what you are looking for but one thing that hasn't been brought up yet is that inner functions can access the variables of their outer functions:
function myFunc(){
var x = "hello";
myInnerFunc();
function myInnerFunc (){
//shows the variable of the outer function
console.log(x);
};
};
Additionally you can use a closure to save the state of an outer functions variables:
function myFunc2(){
var x = "hello";
var timesCalled = 0;
return function (){
timesCalled++;
console.log(x + " called: " + timesCalled);
};
};
var fun = myFunc2();
fun(); //1
fun(); //2
fun(); //3
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.
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