not sure how to access a variable in a function and call the variable back.
Here are some rules:
1. Variables declared inside a function are *local* to the function.
Here is an example of what local to the function means:
function do_stuff() {
var x = 10;
}
do_stuff();
console.log(x);
- x does not exist until the function executes.
- When the function finishes executing, x is destroyed and ceases to exist.
As a result, the line console.log(x);
produces the error:
ReferenceError: x is not defined
The person who asked the question at your second link failed to understand that local variables are destroyed once a function finishes executing, so the username variable in their code cannot be accessed anywhere outside the anonymous function wherein the username variable was declared.
On the other hand, if you don't declare a variable with var, then javascript creates a global variable:
function do_stuff() {
x = 10;
}
do_stuff();
console.log(x); //=>10
That is equivalent to writing:
var x;
function do_stuff() {
x = 10;
}
do_stuff();
console.log(x); //=>10
It's generally considered bad practice for a function to manipulate the value of a variable outside the function. You should prefer the following:
function do_stuff() {
return 10;
}
var x = do_stuff();
In your case, express is the one that is going to be calling your anonymous function, and express just discards any return values. Presumably, express does something like this:
function express_get(func) {
console.log("express_get is executing");
requ = {greeting: 'hello'};
resp = {};
func(requ, resp); //Anything returned by func is not captured in a variable
}
//Here is an attempt to call express_get() and return
//the data rather than setting a global variable:
express_get(function(requ, resp) {
console.log("my callback is executing");
console.log(requ);
return {user_id: 1, room_id: 'A'};
});
--output:--
express_get is executing
my callback is executing
{ greeting: 'hello' }
Because express is calling your request handler function, and because express just discards any return value, there is no way to access the value you returned from the request handler function.
Maybe you are thinking about the problem the wrong way around? Instead of trying to figure out how to get the request data into the io.on('connect') code you should be thinking about how to get the io.on('connect') code inside the route handler function. What happens if you do this:
router.route(...).get(function(req,res){
user_id = req.param('user_id');
room_id = req.param('room_id');
io.on('connection', function(socket){
console.log ( user_id );
console.log ( room_id );
});
});
Based on all the rules discussed in this answer, you should try to determine:
- Can the code inside the anonymous function passed to get() see the io variable?
- Can the code inside the anonymous function passed to io.on() see the user_id and room_id variables?
2. A function's parameter variables are local to the function, too.
Here is an example:
function do_stuff(x) {
console.log(x); //=>hello
}
do_stuff("hello");
console.log(x); //=>ReferenceError: x is not defined
So x does not exist until the function executes, and x ceases to exist when the function finishes executing.
3. Variables declared inside a for loop are NOT local to the for loop.
Here is an example:
function do_stuff() {
for (var x=0; x < 10; ++x) {
console.log(x);
}
console.log(x) //=>10
}
do_stuff();
You can equivalently (and more clearly) write the function above like this:
function do_stuff() {
var x;
for (x=0; x < 10; ++x) {
console.log(x);
}
console.log(x) //=> 10
}
do_stuff();
4. Code inside a function can see the variables that existed in the surrounding scope outside the function at the time the function was *defined*.
Here is an example:
var x = 10;
function do_stuff() {
console.log(x);
}
do_stuff(); //=>10
Pretty simple. The surrounding scope means this:
//First line of program
^
|
| part of do_stuff() surrounding scope
|
v
------------------------+
function do_stuff() { |
//Do stuff |
} |
------------------------+
^
| part of do_stuff() surrounding scope
|
v
---------------------------+
function other_func() { |
|
|
//Do other stuff |
|
} |
---------------------------+
^
| part of do_stuff surrounding scope
|
v
//Last line of program
Note that the region of code inside other_func is not part of do_stuff's surrounding scope, so code inside do_stuff cannot see variables declared inside other_func.
With nested functions, the surrounding scope looks like this:
^ part of inner's surrounding scope
|
|
function outer() {
^
| part of inner's surrounding scope
|
v
----------------------+
function inner() { |
|
} |
----------------------+
^
| part of inner's surrounding scope
v
--------------------------+
function other_inner { |
|
} |
--------------------------+
^
| part of inner's surrounding scope
|
V
}
|
|
V
part of inner's surrounding scope
Here is an example of that:
var x = 10;
function outer() {
function inner() {
console.log(x);
}
inner();
}
outer(); //=>10
And for an anonymous function defined as a function argument, e.g.:
some_func(10, 20, function(req, resp) {.....});
that is almost identical to writing this:
function request_handler(req, resp) {
//Do stuff
}
some_func(10, 20, requestHandler);
And you can figure out the surrounding scope of the request_handler function using one of the diagrams above.
In computer science jargon, javascript functions are known as closures, and javascript functions are said to close over the variables in the surrounding scope that existed at the time the function was defined. If you are reading something that states some function is a closure, you can whisper to yourself, "When the function executes, it can see the variables in the surrounding scope that existed at the time the function was defined."
Here is a more complex example:
function outer() {
var x = 10;
function inner() {
console.log(x);
}
return inner;
}
func = outer();
//outer() has finished executing here.
func();
From rule 1, you might expect that after outer() finishes executing x will be destroyed, and therefore when inner() executes via func(), you will get a not defined error. However, that is not the case. inner() can still see x even though normally x would have been destroyed when outer() finished executing. inner() is said to close over the variables that existed in the surrounding scope when inner was defined.
Here is another example:
function outer() {
var x = 10;
function inner() {
console.log(x);
}
return inner;
}
func = outer();
//outer() has finished executing here.
var x = 20; //New code
func();
What will be the output there? 20? Nope. The inner() function sees the variables in the surrounding scope at the time inner() was defined--not the variables in the surrounding scope at the time inner executes.
One last example:
function outer() {
var funcs = [];
for(var x=0; x < 10; ++x) {
function inner() {
console.log(x);
}
funcs.push(inner);
}
return funcs;
}
ten_funcs = outer();
for(var y=0; y < 10; ++y) {
ten_funcs[y]();
}
What do you think the output will be? It turns out that every one of the ten_funcs outputs 10. That demonstrates that functions close over variables--not values. We know that we can rewrite outer like this:
function outer() {
var funcs = [];
var x;
for(x=0; x < 10; ++x) {
function inner() {
console.log(x);
}
funcs.push(inner);
}
return funcs;
}
So each of the ten_funcs sees the same x variable. After the functions are defined, the x variable that they can see in the surrounding scope is assigned a new value, then when each of the ten_funcs executes, it can see the variable x, and the last value assigned to x was 10. The person who asked the question at your first link was confused about this aspect of variable scoping and which variables the code inside a function can see.
The only other thing that needs to be explained is 'hiding':
var x = 20;
function do_stuff() {
var x = 10;
console.log(x);
}
do_stuff(); //=>10
This is an exception to rule 4. Inside a function, if you declare a variable with the same name as a variable in the function's surrounding scope, javascript creates a new local variable that hides the variable in the surrounding scope.