Modularized JavaScript event handler to increment counters
disclaimer: "bad" is simply a way of saying it's not the best way.

If we were in the early 2000s this would probably be relatively clean code, however javascript has advanced a lot since then (current version: es6)

Take some time to check what's new.



Best practices today is to completely separate HTML / JS / CSS (unless you're using vue, react, angular)


Cleaner code
Logic separation
Reusability
Easier to maintain


So the following should not appear in your HTML.

/// bad
onclick="double_increment()"


/// good
const button = document.getElementById("some_id");
button.addEventListener("click", double_increment);




There is always a better alternative than &lt;br/&gt; and it's not semantic

Don't use it.



const before let and let before var

Always declare your variables with const by default. If you're ok with the variable mutating then use let. Don't use var unless you know what you're doing and you actually need it.

note: pushing an element to an array (declared with const) does not mutate the variable, just the array. Thus no error.



Do not hardcode your html element id in your function.

function Incrementer(name, value) {
   /// bad
   let mydiv = document.getElementById('mydiv'); 
}


It either needs to be sent via the parameter or accessed statically using class

class Incrementer {
   /// still bad though
   static target = "mydiv"
}




Object methods should do what their name infers.

Here, the increment function is supposed to increment the variable, but it does more than that.


Gets the text value of the span
Parses the text value
Increases by one
Updates the UI


(1) is hacky
(2) completely unneeded
(3) the actual thing your function is supposed to do
(4) updates UI ? not what your function says it does

/// bad
that.increment = function() {
        var i = parseInt(that.span.textContent) + 1;
        that.span.innerHTML = i;
}


/// better
that.i = value;

//increments value
that.increment = function() {
        that.i++;
}

//updates UI
that.update = function(){
        that.span.innerHTML = that.i;
}

// Method that should be called on button click
that.handleOnClick = function(){
   that.increment();
   that.update();
}




A double_increment function doesn't need to exist. Each Incrementer should add an event listener to the button click.

/// bad
function double_increment() {
    incrementer1.increment();
    incrementer2.increment();
}


See next section add event listener for solution



Using class and working example

es6 has introduced class


  JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.


Thus your Incremental function should be a class instead.



class Incrementer {

  constructor(incrementId, options) {
  
    const {
      name  = "N/A",
      value = 0,
      target
    } = options;
  
    this.name     = name;
    this.counter  = value;
    this.view     = document.createElement("span");
    
    this.view.id = `#num_${name}`
    
    const button = document.getElementById(incrementId);
    button.addEventListener("click", ()=&gt;this.handleOnClick())

    this.update();        

    const container = document.getElementById(target);
    container.appendChild(this.view);
  }
  
  handleOnClick(){
    this.increment();
    this.update();
  }

  increment() {
    this.counter++;
  }

  update() {
    this.view.innerText = this.counter;
  }
}

const incrementer1 = new Incrementer(
  "increment", 
  {name: "Hello World", value: 3, target: "container"}
);

const incrementer2 = new Incrementer(
  "increment", 
  {name: "Hello World", value: 0, target: "container"}
)
#container {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  align-items: center;
  background-color: darkblue;
}

#container &gt; span {
  padding: 10px;
  background-color: lightblue;
}
&lt;button id="increment"&gt;Increment&lt;/button&gt;
&lt;div id="container"&gt;&lt;/div&gt;