Why am I assigning counter function to count variable? And what is the purpose?
function counter() {
var localVar = 0;
return function() {
localVar++;
return localVar;
}
}
var count = counter(); // I am confused here.
console.log(count());
counter is a function-factory, it returns a function when called.
By assigning a variable to counter you can keep track of this counter and every time you call it the variable localVar will get incremented by one, if you were to always call counter()() you couldn't keep track of that value.
Example:
function counter() {
var localVar = 0;
return function() {
localVar++;
return localVar;
}
}
var count = counter();
for(var i = 0; i<99; i++) count();
console.log(count()); // 100
for(var i = 0; i<99; i++) counter()();
console.log(counter()()); // 1
You aren't assigning the counter function to a variable, you're calling counter and assigning what it returns to the variable.
It's just that counter returns another function.
Note inside counter, there's the bit:
return function() {
localVar++;
return localVar;
}
Which can literally be read as "return a function that increments a local variable, then returns the current state of that variable".
The function counter is a function factory, which is a function that returns a new function—which, in this case, is a function that increments a value.
This new function is then assigned to the variable count.
The usefulness of this pattern is that functions have access to their local scope. So, that function can access and increment the variable localVar in its scope—which is also declared when counter is called—, and no outside functions can modify it, so there are no conflicts of multiple functions changing the same variable. Also, this way you can have multiple counters that don't conflict with each other.
The reason for this is you can use a counter on whatever variable you assign it to so you can keep multiple instances that all keep track independent of one another.
See example below:
function counter() {
var localVar = 0;
return function() {
localVar++;
return localVar;
}
}
var count = counter();
var secCount = counter();
console.log(`count: ${count()}`);
console.log(`count: ${count()}`);
console.log(`secCount: ${secCount()}`);
console.log(`secCount: ${secCount()}`);
console.log(`count: ${count()}`);
console.log(`count: ${count()}`);
console.log(`secCount: ${secCount()}`);
console.log(`secCount: ${secCount()}`);
console.log(`count: ${count()}`);
Related
this not work
function myCounter(){
let counter = 0;
function plus(){
counter++;
return counter;
}
return plus;
}
console.log(myCounter());
console.log(myCounter());
but this work
function myCounter(){
let counter = 0;
function plus(){
counter++;
return counter;
}
return plus;
}
var add = myCounter();
console.log(add());
I know they are different in the syntax.
My main question is:
Why function alone on the console.log does not work and should be attributed to a variable
Your function myCounter only returns a function reference. It does not call the function plus.
In your first example you only call the function myCounter:
console.log(myCounter());
In your second example you first call the function myCounter that returns a function reference:
var add = myCounter();
and then you call the returned function:
console.log(add());
Solution:
You have to change this line
return plus;
to
return plus();
This works:
function myCounter(){
let counter = 0;
function plus(){
counter++;
return counter;
}
return plus();
}
console.log(myCounter());
You are missing the closure concept. Calling a myCounter function will return you another function and it will initialize "private" variable counter inside, so myCounter() -> function.
Of course you can call this way myCounter()(), but in this case the "private" counter variable will be initialized every call with value 0, and won't be useful.
The solution is to store result of myCounter() in variable and call it later, so you will have expected behaviour.
function myCounter(){
let counter = 0;
function plus(){
counter++;
return counter;
}
return plus;
}
console.log(myCounter()());
console.log(myCounter()());
console.log(myCounter()());
console.log('====')
var add = myCounter();
console.log(add());
console.log(add());
console.log(add());
In the second example this line: var add = myCounter(); makes the add var to be only a reference to a function, if you will console log the add var without the brackets, it will print only [Function], but the console.log(add()); makes the add function to be invoked.
In order to make the first example to work, you can change the return statement of the myCounter counter function.
This code make the myCounter to return only the plus function reference:
function myCounter(){
function plus(){
//code
}
return plus;
}
So in order to make it work you should invoke the myCounter twice:
console.log(myCounter()());
But this make the plus function to be invoked when the myCounter is invoked (called) from inside the console.log(myCounter()):
function myCounter(){
function plus(){
//code
}
return plus();
}
function add() {
var counter = 0;
counter += 1;
return counter
}
Why the counter variable dont get incremented after first iteration? output is always 1.
The addfunction is returning the variable counter which is defined inside the function add. The scope of variable counter is local to function, which means each time you invoke the function, it creates a new variable counter and then initialize to zero and then increment the counter.
If you are looking for a counter implementation, then you need to reference the same counter variable every time and increment that variable. This can be implemented by using closure.
Example: In the below example, there are 2 functions, 1 nested inside the another one. The inner function maintains a reference to the outer function Environment, which in this case contains the counter variable. So, even after the control moves out of the function add, the inner functions maintains a reference to counter variable.
var add = (function(){
var counter = 0;
return function(){
return ++counter;
}
})();
document
.querySelector('#btn')
.addEventListener('click', function(){
document.querySelector('#output').textContent = add();
});
<div id="output">0</div>
<button id="btn">Increment</button>
This is a scoping issue. Change it to
let counter = 0;
function add() {
counter += 1;
return counter
}
Or if you want to be able to do add(), use a nested function
function adder() {
let counter = 0;
return function plus() {
return counter += 1;
};
}
let add = adder();
console.log(add());
console.log(add());
console.log(add());
You can make the counter a global variable and then call the add function:
function add(){
counter = counter + 1;
}
I am trying to learn about closures in javascript and I came across the following example:
function counter() {
var count = 0;
return function() {
alert(count++);
}
}
var count = counter();
count();
count();
count();
Which makes sense to me, my question is, why doesn't this work?
var count = function() {
var count = 0;
return function() {
alert(count++);
}
};
count();
count();
count();
To me it seems like it should be the exact same thing but maybe I'm just missing something obvious, please assist.
In order for your second method to work, you will need to call the returned function like this:
var count = function() {
var count = 0;
return function() {
alert(count++);
}
};
count()();
However, doing this, your count number will not increase because it is not being stored anywhere like in the first example, where the variable count holds the function.
So if you want to retain the value of count, use the first method where you say var count = counter()
Hope that clears things up!
I'll try to give a nice explanation right in your code:
function counter() {
var count = 0;
// By calling the function counter (adding a '()' after its name) you are returning a brand new anonymous function
return function() { // **Reference 1**
alert(count++);
}
}
// Here, the count variable is actually the anonymous function you returned in the **Reference 1**
var count = counter();
// In this line, you are calling the anonymous function (adding the '()' after its new name 'count')
count();
The explanation above explain why this works. Because, first you called a function which returned an anonymous function and assigned it to the variable count. Then you called that function by adding the '()' after its name, which executes the alert(count++)
Now, why the other example does not work? I guess it's pretty obvious now:
var count = function() {
var count = 0;
return function() { // **Reference 2**
alert(count++);
}
};
// Here you are calling the count function which returns the anonymous function in the line **Reference 2**.
count(); // So, long story short, this call only returns the anonymous function.
You should try to add a second '()' after it: count()();. This should work as well, because the first '()' returns the anonymous function, and the second one, executes the anonymous function returned.
Hope this helps!
Before you can use the closure, you have to call the outer function to create the closure and get the inner function that is returned and then retain that return result that you can then call subsequent times to use the closure. So, in your second example, you have to call count() and retain it's return result and then use that return result for subsequent calls.
Your second example will work if you change it to this (which looks pretty much the same as the first example):
// log output for purposes of the snippet
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}
var counter = function() {
var count = 0;
return function() {
log(count++);
}
};
// get the inner function and create the closure
var count = counter();
count();
count();
count();
As you can see this only differs from your first example in that counter is a function expression instead of a function definition. Other than the timing of when counter is defined, the second code example is no different and thus the implementation needs to be the same.
So I need a function which increments the value of a variable say n=0. When ever the function runs, the value of this varible must be incremented and it should not be equal to 0 again. For example consider the following code :
function increment(){
var n = 0;
n++;
return n;
}
Now everytime you run this function you get a value of 1. But my requirement is if you run this function for the 1st time, it should be 1, if you run it for the second time, it should be 2 and so on. Unless you refresh the html page and run the function again, it should not be equal to 0. Can anybody help me?
I'm new to coding and any small help is appreciated. Thanks in advance!!!
Create a closure to hold the value
Closures are functions that refer to independent (free) variables.
In short, variables from the parent function of the closure remain bound from the parent's scope.
var increment = (function(n) {
return function() {
n += 1;
return n;
}
}(0)); // -1 if you want the first increment to return 0
console.log(increment());
console.log(increment());
console.log(increment());
You need to declare n outside of the function.
var n = 0;
function increment(){
n++;
return n;
}
The problem is scopes. when you declare a variable inside of a function it is bound to the local scope of the function. as soon as the function is done the variable is gone.
declaring the variable in the root level of the script places it in the global scope.
another way to do this would be to have a variable outside that you're passing around and then you pass it to the function via a parameter.
var i = 0;
function increment(n){
n++;
return n;
}
i=increment(i);
for more information on scopes and variables, review this page: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Values,_variables,_and_literals#Variable_scope
You can bind the data to the function (since functions are objects).
function increment(){
increment.n = increment.n || 0;
return ++increment.n;
}
What about making the number of times increment was called a parameter ?
function increment(numberOfIncrementCalls){
numberOfIncrementCalls++;
return numberOfIncrementCalls;
}
function increment(numberOfIncrementCalls){
numberOfIncrementCalls++;
return numberOfIncrementCalls;
}
n = document.getElementById("demo");
o = document.getElementById("event");
numOfIncr = 0;
o.addEventListener("click",function(){
numOfIncr = increment(numOfIncr);
var insert = numOfIncr.toString();
n.innerHTML = insert;
});
<html>
<p id="demo"></p>
<button id="event">Click me</button>
</html>
var n = 0;
function increment(){
n++;
return n;
}
Learning about scopes will help you greatly. What you want here is the variable 'n' to be of a global scope.
var n = 0; //Declare n outside of the function makes it accessible to the function
//and to any other functions or expressions that want access to n
function inc() {
n++;
}
You can try this code and store the value in localstorage. All time it will be increase old Value untill you have not clear localstorage...
<script>
localStorage.setItem("n", 0);
increment();
function increment(){
let n;
n = localStorage.getItem('n');
n++;
localStorage.setItem("n", n);
return n;
}
</script>
Every time you call a function the value will be incremented by +1 by this method --
let x = 0;
function increment (){
return x = x + 1;
}
This code will always return 501
a=500;
function increment(n){
return n+1
}
increment(a);
You could equate a to the function
a=increment(a);
That would set a to 501, then 502 etc
However consider using an array for the argument instead
a=[500];
function increment(n){
n[0]++;
}
increment(a);
Now it will increment the value of a[0] even though it doesn't have a return statement. The benefit of this is it means we can have multiple arguments and increment them all, and then return some other variable if you like. Like this
a=[0];
b=[5];
function incrementToTen(n,o)
{
n[0]++;
o[0]++;
if(n[0]>=10||o[0]>=10)
{
return true;
}
else
{
return false;
}
}
So after running incrementToTen(a,b) 5 times it will return true
The following code will allow the counter function to be incremented by one every time counter(); is called.
function One() {
var counter = function(initial) {
var c = initial || 0;
return function() {
return c++;
};
}(0);
Too(counter);
}
function Too(counterArg) {
counter();
}
Is there any thing I can replace counter(); with so the counter will decrement? Or even better is there any way for me to set the value of the counter? Like counter = 0 or counter = 20? Also I need to stay away from global variables.
you can assign function as a variable in javascript so now you can do this...
var counter = 0;
var step = 1; // or 20 or whatever
var method = null;
function increment () {
counter += step;
}
function decrement () {
counter -= step;
}
method = icrement;
method();
First, you have a minor typo in your code; presumably you mean
function Too(counterArg) {
counterArg(); // this was just `counter` originally; that will be undefined
}
Second, c++ is a little bit of a weird way to do a counter, since it return c and then increment c, so the counter will start at 0 which is probably not what you want.
(I admit I chuckle a little bit whenever I see c++ in code though. :P )
Okay, on to the main question: I'd do it by adding a method to the counter function called e.g. set.
function One() {
var counter = function createCounter(initial) {
var c = initial || 0;
function counter() {
return ++c;
}
counter.set = function(n) {
c = n;
};
return counter;
}(0);
Too(counter);
}
function Too(counterArg) {
counter(); // 1
counter.set(20); // `c` is now 20
counter(); // 21
counter(); // 22
}
This works because the counter function creates what's called a closure. This is a fairly common concept in JavaScript and there are plenty of good questions and answers about closures on SO that you should look at if you don't know the concept. Basically, even after your anonymous function (which I renamed createCounter) returns, the variable c still exists and can be accessed from any code in createCounter. That's how the counter function works. c cannot, however, be accessed by any code outside createCounter, so if you want to do anything with it, you have to put that code in createCounter. That's what the counter.set method I added does. Since it's within createCounter, it is free to modify c.