I have two different case below. Both case applies the same method javascript closure function. Case 2 output the result as expected but case 1 doesn't, as the increament stops at 1 every time the button is clicked. I know some other closure method to make it work as i expected or increase count every time the button is clicked. But i am just curious why the below case 1 doesn't work while having same method and same way as in case 2 which works though. I hope it makes sense.
case:1
function incrementClickCount() {
var clickCount = 0;
function a() {
return ++clickCount;
}
return a();
}
<input type="button" value="click me" onclick="alert(incrementClickCount());">
case:2
function addNumber(firstNumber, secondNumber) {
var returnValue = 'Result is : ';
function add() {
return returnValue + (firstNumber + secondNumber);
}
return add();
}
console.log(addNumber(10, 20));
You need to return the function a from the incrementClickCount function, at the moment you are returning a() i.e. the result of calling a.
function incrementClickCount(){
var clickCount = 0;
function a(){
return ++clickCount;
}
return a;
}
var incrementer = incrementClickCount();
<input type="button" value="click me" onclick="alert(incrementer())">
A more compact approach is to declare and return the function in one go, with ES6 lambda notation:
function incrementClickCount() {
var clickCount = 0;
return () => ++clickCount;
}
Another piece of advice would be to add a listener to the button rather than using the onclick attribute. The benefits include encapsulating all behaviour within your Javascript, and being able to remove the listener if needed.
function makeIncrementer() {
var clicks = 0;
return () => ++clicks;
}
const incrementer = makeIncrementer();
function clickHandler() {
alert(incrementer());
}
document.getElementById('incrementButton').addEventListener('click', clickHandler);
<button id='incrementButton'>Increment</button>
You need to move the variable outside the function, so you don't keep resetting it back to 0.
var clickCount = 0;
function incrementClickCount() {
function a() {
return ++clickCount;
}
return a();
}
<input type="button" value="click me" onclick="alert(incrementClickCount());">
There's not much point in using the inner function in this case. You can simply write:
var clickCount = 0;
function incremenCount() {
return ++clickCount;
}
Related
I have a code
var variable = 0;
function add() {
return variable += 1;
}
console.log(add());
console.log(add());
Im wonder is there a way to write this code only using function and scope, smth like
function add() {
/* SET INITIAL STATE IF NOT SET*/
/* EXECUTE */
/* RETURN NEW VAL */
}
add(); /* RETURN 1*/
add(); /* RETURN 2*/
to get the same result.
Thank you.
...only using one function...
Your code does use only one function (add). If you mean you don't want it to close over variable, you can store the count elsewhere, for instance as a property on the function itself:
function add() {
if (!add.variable) {
add.variable = 0;
}
return ++add.variable;
}
console.log(add());
console.log(add());
console.log(add());
But of course, that means any code can access and change it.
The usual thing is to close over the variable, and perhaps hide it in a scope where nothing else can see it:
var add = (function() {
var variable = 0;
return function add() {
return ++variable;
};
})();
console.log(add());
console.log(add());
console.log(add());
You can create a pseudo static variable for the function:
(() => {
document.querySelector("#test").addEventListener("click", () => console.log(add(1)));
function add(n) {
add.constant = add.constant || 0;
add.constant += n;
return add.constant;
}
})()
<button id="test">add 1</button>
Also could see the yield operator (generator functions), or console.count()
var add = function () {
var generate = function *inc() {
var i = 0
do {
i++
yield i
} while(true)
}()
return function() {
return generate.next().value
}
}()
console.log(add())
console.log(add())
console.log(add())
I'm trying to call a function without re-initializing (hope I used the correct word here) it every time I call it. So the first time it gets called, it should initialize, but after its initialized, it should just use that reference.
Here's the code I'm trying to do it with.
JSFiddle
console.clear();
function mainFunction(e) {
var index = 0;
function subFunction() {
console.log(index++);
}
return subFunction();
}
window.addEventListener('click', mainFunction)
index should increase by one every time mainFunction gets called. The obvious solution, is to make index a global variable (or just out of mainFunction). But I need index to stay inmainFunction`.
How can I make index increment every time (using the same reference) mainFunction gets called?
I tried assigning mainFunction to a variable, then calling the variable in the event listener,
var test = mainFunction;
window.addEventListener('click', test)
but that didn't work. The results were the same.
You should correct the code as follows;
console.clear();
function mainFunction(e) {
var index = 0;
function subFunction() {
console.log(index++);
}
return subFunction; // <<< don't invoke subfunction
}
window.addEventListener('click', mainFunction()) // <<< invoke mainfunction
maybe try closures?
var main = (function () {
var index = 0;
return function () {return index += 1;}
})();
main()
main()
//index should be 2...
explain-
The variable main is assigned the return value of a self-invoking function.
The self-invoking function only runs once. index initialize only once.
If you don't want to make index global (or one scope higher regarding mainFunction), you can use a closure:
var mainFunction = (function () {
var index = 0;
return function () {return console.log(index++);}
})();
<button onclick="mainFunction()">Click</button>
Using OOP concept is the proper way to achieve this. The following should help you.
If you want to do it in ES6 way follow this babel example
var mainFunction = function(val) {
this.index = val //initialize this with the fn parameter or set a atatic value
}
mainFunction.prototype.subFunction = function() {
return this.index++
}
var instance = new mainFunction(0)
window.addEventListener('click', function() {
console.log(instance.subFunction())
})
<p>Click to see the result </p>
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.
I followed a tutorial online on how to build a calculator using javascript. The code uses a for loop to go through all the buttons of the calculator and 2 functions to add the numbers and to calculate.
Here is the code:
for (var i = 0; i < buttons.length; i += 1) {
if (buttons[i].innerHTML === "=") {
buttons[i].addEventListener("click", calculate(i));
}
else {
buttons[i].addEventListener("click", addValue(i));
}
}
function addValue(i) {
return function() {
if (buttons[i].innerHTML === "~" ) {
result.innerHTML += "/";
}
else if (buttons[i].innerHTML === "x") {
result.innerHTML += "*";
}
else {
result.innerHTML += buttons[i].innerHTML;
}
};
}
function calculate(i) {
return function() {
result.innerHTML = eval(result.innerHTML);
};
}
I want to ask why the 2 functions, addValue and calculate return functions? If i remove the return, the code will not work. Why?
If you remove the return statement then addValue returns undefined.
addEventListener expects two arguments, the name of the event to run a function on, and the function to run.
If addValue returns undefined then you are passing undefined to addEventListener instead of a function.
The line:
buttons[i].addEventListener("click", calculate(i));
At the moment it is called, it calls calculate(i). This then returns the function that will be called by the event handler. The event handler is not calling calculate(i) but the function returned from it.
returning function throw a function is the property of JavaScript named closure ,generally with the functions we get a solved value through return statement but when our variable is not solved then we can pass a function as return value for further computation
When a function returns another function or recives functions as parameters that is called
High Order Function
Wikipedia
This is just a feature that some languajes offer us.
e.g:
function addTextTag(idTag) {
return function(text) {
document.querySelector('#'+idTag).innerHTML = text;
}
}
var containerChange = addTextTag('container');
//calling addTextTag with first parameter return a function
// that would receive another parameter
containerChange('tag says that');
containerChange('Now says this');
//here we can call first function and pass directly parameter to the function returned
addTextTag('otherId')('Other Text');
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