Gain Access To variables defined within functions - javascript

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);

Related

Function defined in setTimeout has access to the outer variables in JavaScript

I know that this keyword always refers to the this of the current scope, which changes any time you wrap something in function() { ... }. My question is, why do I have access to the outer scope variable x in the function inside the setTimeout function?
var x = 45;
function getRecipe(recipe) {
x = 35;
return {
displayRecipe: function(a) {
//here we have access to x=35
setTimeout(function() {
//why do we have access to x=35 and to recipe here?
console.log(this.x + a + recipe);
}, 1500)
}
}
}
getRecipe("noodles").displayRecipe(2);
When not in strict mode, and when the this is not set by the call, this inside functions will default to the global object (window in browsers).
function f1() {
return this;
}
console.log(f1() === window); // true
Also in browsers when not in strict mode, global variables (variables declared in the global scope) declared with var are also created as members of the global object.
var foo = "foobar";
console.log(foo === window.foo);
Because your x is declared as a global variable, it is also added as a member of the window object. Because your setTimeout callback does not explicitly set the this scope, it also defaults to the global object, and so it is possible you can access x via this.
If x would not have been declared in the global scope (or would've been declared in strict mode or with a let/const statement), you would not be able to access it:
(function() {
var x = 45;
function getRecipe(recipe) {
x = 35;
return {
displayRecipe: function(a) {
//here we have access to x=35
setTimeout(function() {
//why do we have access to x=35 and to recipe here?
console.log(this.x, a, recipe);
}, 1500)
}
}
}
getRecipe("noodles").displayRecipe(2);
})();
You should put let before x=35
var x=45;
function getRecipe(recipe){
let x=35;
return{
displayRecipe: function(a){
//here we have access to x=35
setTimeout(function(){
//why do we have access to x=35 and to recipe here?
console.log(this.x + a + recipe );
},1500)
}
}
}
getRecipe("noodles").displayRecipe(2);

Why is the function returned from a callback function not forming closure over the function where it is called?

I am having trouble in understanding the output from the below code (In Javascript) :
function outerFunction(callback){
var x =10;
var myCallbackRet = callback();
myCallbackRet();
}
outerFunction(function(){
return function(){
console.log(x); //output - x is not defined
}
});
As far as i understand when function myCallbackRet is called then [[Scope]] property of myCallbackRet is set to the Scope chain of the outerFunction and so the variable x should be accessible inside `myCallbackRet'.
Why is the output 'undefined'? Thanks a lot in advance.
Basically it has to do with where your function is defined. It was defined out of scope. Closure only works when a function is defined some where. Setting a variable to a function and calling it doesn't make everything above it available inside the function being called or there would be no reason to pass parameters to a function. Something like this would work.
function outerFunction(callback){
var x =10;
var myCallbackRet = callback();
myCallbackRet(x);
}
outerFunction(function(){
return function(y){
console.log(y);
}
});
Or this:
function outerFunction(callback){
var myCallbackRet = callback();
myCallbackRet();
}
outerFunction(function(){
var x =10;
return function(){
console.log(x);
}
});
Your anonymous function
function(){
return function(){
console.log(x)
is defined on the same scope (global) as outerFunction, but x is defined inside the scope outerFunction.
The scope of the function is set at the moment the function is defined, rather than at the moment when a function is assigned to variable.

nodejs express: store parameters in variable

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.

Access local variable inside a callback function

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.

Understanding Local Scope

I can't manage to change the value of 'i' no matter how hard I try...
My code is the following:
function changeValue(){
//neither 'var i=99;' or 'i=99;' interferes with the 'i' on myFunction
}
function myFunction(){
var i;
for(i=0;i<3;i++){
alert(i);
changeValue();
alert(i);
}
}
myFunction();
My question: How can I change the value of 'i' (on MyFunction) using the changeValue function?
Also: I badly need read some guides about this, could someone give me a link to a good one?
Move changeValue() to be in the same scope as i:
function myFunction(){
var i;
for(i=0;i<3;i++){
alert(i);
changeValue();
alert(i);
}
function changeValue() { i = 99; }
}
Or, put i in the same scope as changeValue():
var i;
function changeValue() { i = 99; }
function myFunction(){
// var i; // don't define i here
for(i=0;i<3;i++){
alert(i);
changeValue();
alert(i);
}
}
Alternatively, you can tell changeValue() what the value of i is, then have it return the new value:
function changeValue(i) {
return i + 1;
}
Then:
i = changeValue(i);
Edit: To illustrate scope:
var a = 0; // global scope - accessible everywhere via a
// unless overridden by a locally scoped a
// always accessible via window.a
function doSomething () {
var a = 1; // local scope - you can still access window.a
var b = 2; // local scope - accessible to child scopes, but not global scope
function innerFunction () {
var a = 3; // you no longer have access to the parent function's a variable
// you can still access window.a
var c = 4; // only accessible here (since no child scopes exist)
alert(window.a); // 0
alert(a); // 3
alert(b); // 2
alert(c); // 4
}
innerFunction();
alert(window.a); // 0
alert(a); // 1
alert(b); // 2
alert(c); // undefined - unavailable in this scope
}
doSomething();
alert(window.a); // 0
alert(a); // 0
alert(b); // undefined - unavailable in this scope
alert(c); // undefined - unavailable in this scope
You could simply return the value :
function changeValue(i) {
return i + 2;
}
for(i=0;i<3;i++){
alert(i);
i = changeValue(i);
alert(i);
}
function myFunction(){
var i;
for(i=0;i<3;i++){
alert(i);
i = changeValue();
alert(i);
}
}
while changeValue():
changeValue(){
return new_i;
}
You can only manipulate variables that are inside your scope. Currently, the scope of i is confined to myFunction().
This is an excellent article to get you started understanding the scope rules in JavaScript.
Both changeValue and myFunction exist in the global scope. If you define i in myFunction, it's only accessible inside myFunction and its children, functions defined inside myFunction. The 'scope chain' (I'm just thinking up a word for it) looks like this:
myFunction <- window
changeValue also exists in the global scope. It is called from myFunction, but that doesn't change the scope in which it exists. Its scope chain is like this:
changeValue <- window
If you only use changeValue inside myFunction, you can do this:
function myFunction() {
function changeValue() { /* stuff */ }
/* more stuff */
}
changeValue's scope chain is now like this:
changeValue <- myFunction <- window
As i exists in myFunction, it now also exists in changeValue.
when you are using var within myFunction, it becomes a local variable in that scope. So you can't access it anywhere outside not matter how hard you try.
Use window.i instead of var i in both places and it should work,
You can simply avoid window. and use i directly without var prefix or even place the var i declaration outside both the functions... but effectively the variable become a part of the window object. (In general all global variable in JS are part of the window object)

Categories