srs
srs

Reputation: 35

Closures in javascript with different case

I have two different cases below. Both cases apply the same method Javascript closure function. Case 2 output the result as expected but case 1 doesn't, as the increment 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));

Upvotes: 0

Views: 39

Answers (2)

Alex Young
Alex Young

Reputation: 4039

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>

Upvotes: 1

Barmar
Barmar

Reputation: 781721

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

Upvotes: 1

Related Questions