I am still new with nodejs, still not sure how to access a variable in a function and call the variable back.
check few links: but im getting really confused. Please help!
Node.JS: How to pass variables to asynchronous callbacks?
How can we access variable from callback function in node.js?
var express = require('express');
var app = express();
var router = express.Router();
var https = require('https').createServer( ssl_options, app);
var io = require('socket.io')( https );
**var user_id;
var room_id;**
router.use(function(req, res, next) {
next();
});
app.use('/chat',router);
router.route( '/chat/:user_id/:room_id' )
.get(function(req,res){
res.sendFile( __dirname + '/index.html' );
user_id = req.param('user_id');
room_id = req.param('room_id');
});
https.listen(3000);
io.on('connection', function(socket){
**console.log ( user_id );
console.log ( room_id );**
});
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.
Related
Within Js Functions, a variable can be defined but from console that variable doesn't exist is there anyway to access or edit it?
Example:(This code would be in the website)
function whatever () {
var x = 10
}
then in console if you type
x
it will say 'undefined'
x is limited to the scope of its function. If you want to reference it outside of the function, you can either declare it outside the function:
var x = 10
function whatever () {
// ...
}
Or you can make it a global variable by declaring it with the window object:
function whatever () {
window.x = 10
}
whatever()
console.log(x)
What you're talking about is called scope. From Mozilla's docs:
function exampleFunction() {
var x = "declared inside function"; // x can only be used in exampleFunction
console.log("Inside function");
console.log(x);
}
console.log(x); // Causes error
However:
var x = "declared outside function";
exampleFunction();
function exampleFunction() {
console.log("Inside function");
console.log(x);
x = "something else";
}
console.log("Outside function");
console.log(x);
In other words, declaring variables outside the function allow access, and you can change them from within.
Alternatively, building on their example, you can use a return value in the function to assign a variable its value.
function exampleFunction() {
return "Inside function";
}
const x = exampleFunction();
console.log(x);
var inner = function() { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(); })(inner);
// test 2
(function(cb) { var x = 123; cb.apply(this); })(inner);
// test 3
(function(cb) { var x = 123; cb.bind(this)(); })(inner);
// test 4
(function(cb) { cb.bind({x: 123})(); })(inner);
All tests result in:
ReferenceError: x is not defined
Do someone know how it is possible to access 'x' as a local variable inside the callback?
Fact: when you do var inner = function() { console.log(x); } in your first line, x is not defined. Why? Because, inside your inner function, there's no local declaration of x (which would be done with var x = something). The runtime will then look up in the next scope, that is the global scope. There isn't, also, a declaration of x, so x is also not defined there.
The only places where there is a variable called x are inside each one of your 4 IIFEs following. But inside the IIFEs, each x is a different variable, in a different scope. So, if what you want is to console.log() the x defined inside each IIFE, you are taking the wrong approach.
Keep in mind that, when you define inner, you are capturing the environment inside the function's closure. It means that, whatever value could x have there (in the declaration of the function), would be the available value to the x variable later, when the inner function would be used. The fact that your x there is not defined is only an accessory, and is not what is causing the undesired behavior.
So, what happens is that when you call your inner function inside any of your IIFEs, the x referred to inside the inner function declaration is a captured value of what x had as a value when the function was defined, not the value that x has now in the scope where the function is currently being called. This is what is called lexical scope.
To solve this, you would have to pass the value that you want to console.log() inside the inner function as a parameter to the inner function, as so:
var inner = function(x) { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(x); })(inner);
The only way to access the local variable x in the callback, is to pass it as an argument:
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb(x); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.apply(this,[x]); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.call(this,x); })(inner);
FURTHER
Because JS is lexically scoped, trying to reference the local variable after the anonymous function has finished executing is impossible by any other means. If you don't pass it as an argument to make it available elsewhere, JS will see it as non-reachable and it will be eligible for garbage collection.
You could redefine the callback function in the current scope:
var inner = function() { console.log(x); }
(function(cb) { var x = 123; eval('cb = ' + cb.toString()); cb(); })(inner);
// or
(function(cb) { var x = 123; eval('(' + cb.toString() + ')')(); })(inner);
This will not work if the function relies on anything in the scope in which it was originally defined or if the Javascript file has been minified. The use of eval may introduce security, performance, and code quality issues.
Have you tried using events? Emit an event inside the anonymous function, then subscribe to it in your own function somewhere else that carries out your logic.
I understand functions in 'js' have lexical scope (i.e. functions create their environment (scope) when they are defined not when they are executed.)
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined
When I run just 'f()' it returns the inner function. Which I get, that's what 'return' does!
function f() {
var b = "barb";
return function() {
return b;
}
}
console.log(b); //ReferenceError: b is not defined
Why do you get 'ReferenceError: b is not defined?'
But doesn't the inner function above have access to it's space, f()'s space etc. Being that 'b' is being returned to the global space, wouldn't the console.log() work?
However when I assign 'f()' to a new variable and run it:
var x = f();
x();// "barb"
console.log(b); //ReferenceError: b is not defined
This returns 'b' which is "barb", but when you run console.log() again you'll get 'ReferenceError: 'b' is not defined'; Isn't 'b' in the global scope now since it has been returned? SO why didn't 'x()' also return the inner function just like 'f()' did?
You, my friend, are thoroughly confused. Your very first statement itself is wrong:
functions create their environment (scope) when they are defined not when they are executed
Actually it's the opposite. Defining a function doesn't create a scope. Calling a function creates a scope.
What's a scope?
To put it simply, a scope is the lifespan of a variable. You see, every variable is born, lives and dies. The beginning of a scope marks the time the variable is born and the end of the scope marks the time it dies.
In the beginning there's only one scope (called the program scope or the global scope). Variables created in this scope only die when the program ends. They are called global variables.
For example, consider this program:
const x = 10; // global variable x
{ // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
} // end of the scope
console.log(x); // 10
Here we created a global variable called x. Then we created a block scope. Inside this block scope we created a local variable x. Since local variables shadow global variables when we log x we get 20. Back in the global scope when we log x we get 10 (the local x is now dead).
Block Scopes and Function Scopes
Now there are two main types of scopes in programming - block scopes and function scopes.
The scope in the previous example was a block scope. It's just a block of code. Hence the name. Block scopes are immediately executed.
Function scopes on the other hand are templates of block scopes. As the name suggests a function scope belongs to a function. However, more precisely, it belongs to a function call. Function scopes do not exist until a function is called. For instance:
const x = 10;
function inc(x) {
console.log(x + 1);
}
inc(3); // 4
console.log(x); // 10
inc(7); // 8
As you can see every time you call a function a new scope is created. That's the reason you get the outputs 4, 10 and 8.
Originally, JavaScript only had function scopes. It didn't have block scopes. Hence if you wanted to create a block scope then you had to create a function and immediately execute it:
const x = 10; // global variable x
(function () { // beginning of a scope
const x = 20; // local variable x
console.log(x); // 20
}()); // end of the scope
console.log(x); // 10
This pattern is called an immediately invoked function expression (IIFE). Of course, nowadays we can create block scoped variables using const and let.
Lexical Scopes and Dynamic Scopes
Function scopes can again be of two types - lexical and dynamic. You see, in a function there are two types of variables:
Free variables
Bound variables
Variables declared inside a scope are bound to that scope. Variables not declared inside a scope are free. These free variables belong to some other scope, but which one?
Lexical Scope
In lexical scoping free variables must belong to a parent scope. For example:
function add(x) { // template of a new scope, x is bound in this scope
return function (y) { // template of a new scope, x is free, y is bound
return x + y; // x resolves to the parent scope
};
}
const add10 = add(10); // create a new scope for x and return a function
console.log(add10(20)); // create a new scope for y and return x + y
JavaScript, like most programming languages, has lexical scoping.
Dynamic Scope
In contrast to lexical scoping, in dynamic scoping free variables must belong to the calling scope (the scope of the calling function). For example (this is also not JS - it doesn't have dynamic scopes):
function add(y) { // template of a new scope, y is bound, x is free
return x + y; // x resolves to the calling scope
}
function add10(y) { // template of a new scope, bind y
var x = 10; // bind x
return add(y); // add x and y
}
print(add10(20)); // calling add10 creates a new scope (the calling scope)
// the x in add resolves to 10 because the x in add10 is 10
That's it. Simple right?
The Problem
The problem with your first program is that JavaScript doesn't have dynamic scoping. It only has lexical scoping. See the mistake?
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined (obviously - f2 can't access the `a` inside f1)
Your second program is a very big mess:
function f() {
var b = "barb";
return function() {
return b;
}
}
console.log(b); //ReferenceError: b is not defined
Here are the mistakes:
You never called f. Hence the variable b is never created.
Even if you called f the variable b would be local to f.
This is what you need to do:
function f() {
const b = "barb";
return function() {
return b;
}
}
const x = f();
console.log(x());
When you call x it returns b. However that doesn't make b global. To make b global you need to do this:
function f() {
const b = "barb";
return function() {
return b;
}
}
const x = f();
const b = x();
console.log(b);
Hope this helped you understand about scopes and functions.
You get, "ReferenceError: b is not defined" because "b" is not defined where your console.log() call is. There's a "b" inside that function, but not outside. Your assertion that "b is being returned to the global space" is false.
When you invoke the function returned by your "f()" function, that will return a copy of the value referenced by that closure variable "b". In this case, "b" will always be that string, so the function returns that string. It does not result in the symbol "b" becoming a global variable.
But doesn't the inner function above have access to it's space, f()'s space etc.
Yes it has. It accesses the b variable and returns its value from the function.
Being that 'b' is being returned to the global space
No. Returning a value from a function is not "making a variable available in the caller scope". Calling the function (with f()) is an expression whose result is the value that the function returned (in your case, the unnamed function object). That value can then be assigned somewhere (to x), a property of it can be accessed or it can be discarded.
The variable b however stays private in the scope where it was declared. It is not [getting] defined in the scope where you call console.log, that's why you get an error.
What you want seems to be
var x = f();
var b = x(); // declare new variable b here, assign the returned value
console.log( b ); // logs "barb"
function f1() {
var a = 1;
f2();
}
function f2() {
return a;
}
f1(); // a is not defined
f2(); does not knows about the a,because you never passed 'a' to it,(That's Scope are
created when the functions are defined).Look function f2() would have been able to acess
a if it was defined inside f1();[Functions can access the variables in same scope in
which they are "DEFINED" and NOT "CALLED"]
function f() {
var b = "barb";
return function(){
return b;
}
}
console.log(b);
First of all You Need to Call f(); after executing f(); it would return another function
which needs to be executed. i.e
var a=f();
a();
it would result into "barb" ,In this case you are returning a function not the var b;
function f() {
var b = "barb";
return b;
};
console.log(f());
This would print barb on screen
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!
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
}