Do, inner and outer functions get their own copy of same variable? - javascript

just a bit confused by this code
var counter = function() {
//...
var count = 0;
return function () {
return count = count + 1;
}
}
var nextValue = counter();
console.log(nextValue());
nextValue.count = 7;
console.log(nextValue());
console.log(nextValue.count);
console.log(nextValue());
Output is
1
2
7
3
It's counter intuitive. There are two representations of count. One on the outerfunction nextValue and one that only the inner anonymous function can see.
Correct, or are my missing something?

The expression nextValue.count does not refer to the local variable "count" declared inside the function. It is not possible, in fact, to create a reference to a variable local to a function from code outside the function. What you're referencing there is simply a property of the function object.
So, yes, the "count" variable that the returned function has access to is effectively completely private to that function, and it is persisted in the closure formed by the call to the "counter" function.
If you did want that to work, you could do this:
function counter() {
function actual() {
return actual.count = actual.count + 1;
}
actual.count = 0;
return actual;
}
edit — (fixed bogus code) the name "actual" inside gives the returned function safe access to the function object itself; originally I typed "this" there, and that would not work unless the external code set it up explicitly.

The way you describe it, count is effectively a private variable. When you're assign to nextValue.count, you're creating a separate property--not accessing the internal count being incremented by your counter.

Related

If a variable is created within the scope of a function that returns a function that uses that variable. Is it possible to acces that variable outside

function creatPrintNumFunction()
{
var num= 12;
return function printNum()
{
console.log(num);
}
}
var printer = creatPrintNumFunction();
printer.num =13; //this part doesn't work but is there a way to access this Num variable Outside the creatPrintNumFunction, The printer function must be finding the num variable from somewhere.
printer();
So how can I get this code to print 13 instead of 12 most importantly with out changing any of the code of the createPrintNumFunction().
For more context on what I really need to use this theory for. I'm using an external module express-sessions in node.js that I don't want to change. There is this 'store' variable where all the sessions are stored that I need to access only problem is that it's created within a function.There is another way i could access it but it's not really convenient
Looking for something like this?
function creatPrintNumFunction() {
const f = function printNum() {
console.log(f.num);
};
f.num = 12; // set .num property to initial value
return f; // return function "printNum"
}
var printer = creatPrintNumFunction();
printer.num = 13;
printer();
printer.num = 42;
printer();
There is this 'store' variable where all the sessions are stored that I need to access only problem is that it's created within a function. There is another way i could access it but it's not really convenient
No there is no way to access store without modifying the code. And you shouldn't modify the code of an external module, because store is likely made inaccessible for a reason. Changing the code might result in a code base that would prevent you from updating the express-sessions.
Having the need to do that sounds like an XY-Problem.
If it is your code and you want to allow the variable to be accessed there are different ways to do that. You for sure could move var num outside of creatPrintNumFunction (as described in the answer of alonealgorithm but that breaks the encapsulation you had before. Whether that is a good idea or not depends on the actual use case. But you need to be aware that if you do that that every "print" function returned from creatPrintNumFunction then uses the same variable.
Let's say you don't want to move num out of the scope of creatPrintNumFunction because every "print" function returned from creatPrintNumFunction should have its own num variable.
What then you could do is to create another function (e.g. set) within creatPrintNumFunction that can change num and assign this function as a property to the function you return from creatPrintNumFunction.
function creatPrintNumFunction() {
var num = 12;
// both "set" and "printNum" create here
// have a closure over the same "num" variable
function set(val) {
num = val;
}
function printNum() {
console.log(num);
}
// the "set" function is assigned as a parameter to your
// printNum function
printNum.set = set;
return printNum;
}
var printerA = creatPrintNumFunction();
var printerB = creatPrintNumFunction();
printerA.set(13)
printerB.set(23)
printerA();
printerB();
The advantage of this approach is that you don't expose num and you can control in your set function how/if num can be changed.
So, the comment you wrote about printNum() function being able to access the num variable somehow is due to JavaScript closures. Closures are an important JavaScript topic which I would recommend looking at some online resources or this stackoverflow post JavaScript closures to learn about. Essentially when you return the printNum function from createPrintNumFunction, the printNum function will remember the num variable that was declared in createPrintNumFunction. But to answer your question of whether you can access the variable outside of the scope it was declared in, then the answer is no. An outer scope cannot access variables from an inner scope. Inner scopes can access variables from outer scopes. So, unless you are keeping track of the num variable from outside of the scope that it was declared in, you won't be able to access the value num holds outside of the scope it was declared in.
So, here you can change the value of num inside of the printNum function itself like this:
function creatPrintNumFunction() {
var num = 12;
return function printNum() {
num = 13;
console.log(num);
};
}
var printer = creatPrintNumFunction();
printer.num = 13; //this part doesn't work but is there a way to access this Num variable Outside the creatPrintNumFunction, The printer function must be finding the num variable from somewhere.
printer();
You could define a global variable that keeps track of the num variable. Then through the scope chain the value used inside of the printNum function for the num variable will resolve to the value your global variable currently contains like so:
var num = 12;
function creatPrintNumFunction() {
return function printNum() {
console.log(num);
};
}
var printer = creatPrintNumFunction();
num = 13; //this part doesn't work but is there a way to access this Num variable Outside the creatPrintNumFunction, The printer function must be finding the num variable from somewhere.
printer();
I'm sure there are other methods to go about this as well but I hope that one of the above methods fits your need.

javascript closure Immediately Invoked Function Expression

I'm trying to get a deeper understanding of javascript closures , reading about the subject i ran into many similar examples to the following function:
function idCreator(listOfItems) {
var i;
var uniqueID = 100;
for (i = 0; i < listOfItems.length; i++) {
listOfItems[i]["id"] = function (j) {
return function () {
return uniqueID + j;
}()
}
(i);
}
return listOfItems;
}
I understand the main concept of using IIFE inner function and passing the counter variable as a parameter , so for instance in the above example we will be returning the right i (index) , and not the value we get after the end of the loop.
My question is why return an anonymous function, wouldn't returning the value itself work the same?
something like:
function iDCreator(listOfItems) {
var i;
var uniqueID = 100;
for (i = 0; i < listOfItems.length; i++) {
listOfItems[i]["id"] = function (j) {
return uniqueID + j;
}
(i);
}
return listOfItems;
}
The only reason I see to use closures and IIFE's in the example you provide, would be pedagogical: to show how you can swap code with an IIFE, and get the exact same result. Furthermore, it shows how inner functions can still access outer variables.
As said by Quentin, in this very example there is no other logical reason to use closure and IIFE. It is even counter-productive (slows down performance and obfuscates code).
By "definition", an IIFE ("immediately invoked") is not called later on. Its main (and probably only) use is to provide a function scope / closure (as if it were a "block" in other languages that provide block scope), while still avoiding having to use a normal function declaration, where you have to choose an identifier which may collide with another one defined somewhere else.
// Normal function declaration:
function someIdentifier() {}
// Let's immediately call it to execute the code.
someIdentifier();
// what happens if "someIdentifier" was defined somewhere else?
// For example in a previous loop iteration?
That is why the author had to use IIFE's within its for loop.
Within a scope / closure, you can use whatever identifiers (for variables and function declarations) you need, while preventing any collision with identifiers outside the scope. Whether using a function declaration, a function expression, or an IIFE.
// Using an Immediately Invoked Function Expression:
(function idForRecursion() { // being a Function Expression rather than a declaration, you can even use an identifier here to be used for recursion, and it will not pollute the global scope.
var anyIdentifier;
// If "anyIdentifier" were defined outside, this local definition will "shadow" it for the current closure only, without affecting / polluting the outside definition and value.
// As in normal closures, you can still access variables outside the IIFE.
alert(myGlobalVar);
})();
Therefore maybe a more pedagogical example for closure would have been an IIFE where the uniqueID were inside and incremented but hidden from global scope (through a closure) so that no one can fiddle / interfere with it:
var iDCreator = (function () {
var uniqueID = 100; // initial value.
return function innerFn(listOfItems) {
for (var i = 0; i < listOfItems.length; i += 1) {
listOfItems[i]["id"] = uniqueID;
uniqueID += 1;
}
return listOfItems;
};
})(); // "iDCreator" is now a reference to the "innerFn" which has a closure with "uniqueID", but the latter is not accessible from global scope.
// Calling "iDCreator" several times gives truly unique id's, incremented from the previous call.
There's no need to use a function at all.
for (i = 0; i < listOfItems.length; i++) {
listOfItems[i]["id"] = uniqueID + i;
}
Using a closure can be useful when you are assigning a function that will be called later. It isn't here. It looks like the author of the code just got carried away.

Why cannot use function name to retrieve property in JavaScript?

The following is the code
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
console.log(add.num); //outputs :undefined
Function name can be treated as reference of a function object, so the num is the property of add function object, the outputs could have been 0. But the result is not like so, why?
If i change the code to:
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
var obj = new add();
console.log(obj.num); //outputs : 0
it works correctly. Can anyone explain this? Many many many thanks.
this refers to current instance of your function. until you create a new instance using new add() this will refer to window object.
add.num will check if add has a property named num. Which is false because add refers to a function definition not an instance/object of function.
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
console.log(add.num); //outputs :undefined because add=function(){};
while in another case, when you create object using new it returns you a javascript object having all the public properties.
///obj=Object{ num : 0};
function add() {
var counter = 0;
this.num = 0;
function plus (){ return counter +=1;}
plus();
return counter;
}
var obj = new add();
console.log(obj.num); //outputs : 0 because obj is {num:0}
Fiddle to play: http://jsfiddle.net/ZpVt9/76/
It will help to read-up on this in JavaScript: MDN
When you do new add(), the interpreter creates a new JavaScript Object/Hash and binds it to this variable in the function. So this is valid inside the scope of the function.
When you don't do a new you are calling the function without a context, so this is undefined in such cases (in 'use strict' mode).
You can explicitly pass a context to Functions using Function.apply/Function.call/Function.bind
this inside a function points to different object depending on how the function is called:
If the function is called in the global context (outside any function) this points to global object (which is window if the script is executed within a browser).
console.log(this === window) will output true.
If this is referred inside a function, then it depends if we have set strict mode.
If the code is in strict mode then this will be undefined unless we explicitly assign it to something.
If the code is not in strict mode then this will point to global object. (Which is again window if script is executed in a browser).
If function is used as constructor to make new objects then this points to the new object being made.
If function is used as object method then this points to the object method is called on.
More explanation with examples here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Every function is an object in JavaScript. But as you can see from above explanation none of the ways this points to function object itself from the same function body. Thus the only way you can set function's property is by directly assigning it to the function without using this.
There is another way of adding a property to functions. This is a very bad idea of doing so as adding any property this way will reflect in all functions used. Every function is linked to Function.prototype object. Thus adding any property in this object will get reflected in all functions.
Function.prototype.someProperty = 1;
//now try accessing it via any function object
console.log(add.someProperty); //should print 1 to console.
"num" is not a property of the "add" function is a property of the object created and returned by that function if you want to add num to your add function you need to do
add.prototype.num=0;
and remove it from your objects definition

javascript - setting global variables inside a function

I am trying to create a function which will dynamically set the value of whatever global variable is passed as a parameter. It's not working, and I'm trying to figure out why. Can someone please explain why this doesn't work:
var things = 5;
function setup(variable) {
variable = 7;
}
setup(things);
console.log(things); //should return 7. returns 5 instead. the function had no effect on the global variable
and this also doesn't work:
var things = 5;
function setup(variable) {
window.variable = 7;
}
setup(things);
console.log(things); //should return 7, but returns 5. still not accessing the global variable.
but this does:
var things = 5;
function setup(variable) {
window[variable] = 7;
}
setup("things");
console.log(things); //returns 7
I suspect that what is happening is that the parameter variable is being set as a local variable inside of the function, so any changes are only happening to the local version. But this seems strange because the parameter that's been passed is a global variable. Can someone explain to me what is happening and how to better write this code? Does this require a method (which can then use this to access the original object)?
Thanks!!
Javascript is pass-by-value. (Objects, arrays, and other non-primitives are passed by value-of-reference.) That means that the value of the variable (or reference) is passed to the function, but the function parameter does not become an alias for the actual argument. Thus, you cannot change a variable outside a function without referencing it (as you do in your last example).
See this answer in another thread for more information.
Inside of functions are "variable environments". When the function setup is declared, and the parameter variable set, it creates a local variable in setup's variable environment for variable (the parameter).
So that is why this assignment
function setup(variable) {
variable = 7;
}
Will never change the value sent to variable.
Variables in JavaScript are values. As the variable is passed around, the only thing passed is the value of the variable. However, the value of the variable is assigned to the parameter (again poorly named in this example) variable. When the value of the parameter is assigned to 7, that only changes the local variable, and not the value of the passed variable.
//the value of things is 5
var things = 5;
//the passed value 5 is assigned to variable
function setup(variable) {
//the value of variable is changed to 7 (and nothing is done with 5)
variable = 7;
}
//the value of things is sent to setup
setup(things);
Hopefully this will be a little more enlightening. Consider a situation where setup was actually modifying the value of variable. A good example is when the value has state, such as an array or an object.
//the value of things this time is an object
var things = {};
//the passed value of object is assigned to variable
function setup(variable){
//the value of variable (the object) has a property added named msg with a value of "hello world"
variable.msg = "hello world";
}
//the value of things (an object) is sent to setup
setup(things);
alert(things.msg);//hello world
When variables are passed as arguments to functions, a copy of their value is made and assigned to the name of the argument in the function.
For example:
function foo(a) {
a = 7; // sets the temporary variable(argument) a to 7
}
var bar = 24;
foo(bar); // copies bar's value and passes in the copy to foo
For a function to modify a variable itself, you would have to access it another way. In other languages there are things called pointers that point to a place in memory. This allows you to modify variables directly, as you have where they are located - you can simulate this with JavaScript:
var spam = 3;
var memory = ["bar", 29, "x", foo, false];
function foo(a) {
memory[a] = 7;
}
foo(3);
The above example sets an array called memory and fills it with random gibberish. Then, a function named foo is created that allows for the modification of elements in this memory array.

Passing variable as argument in closure

I'm studying closures and found the following example code for incrementing a "private" variable named count:
function setup() {
var count = 0;
return function() {
count += 1;
console.log(count);
}
};
var next = setup();
next();
This makes sense to me. However, when I experimented with passing the variable as an argument to the nested function, next() logs 'NaN' to the console. Eg:
function setup() {
var count = 0;
return function(count) {
count += 1;
console.log(count);
}
};
var next = setup();
next();
Can someone explain why this happens?
Can someone explain why this happens?
Inside the closure, count now refers to the parameter, function(count) {. Since you are not passing any argument when you call the function, count is undefined and adding a number to undefined results in NaN.
when I experimented with passing the variable as an argument to the nested function
To be clear: The count parameter has nothing to do with the count variable defined in the outer function. You are not passing the variable as argument, because you are not calling the function, you are defining it.
It's because the inner function now has access to a more local variable, so it doesn't look at any closures it has access to for the "count" variable. And nothing is passed, so count is undefined.
This answer may be useful: Scope Chain in Javascript

Categories

Resources