JavaScript clicker game I'm studying JavaScript and jQuery and I did an implementation of a simple cat clicker game:



class Cat {
  constructor(name, picture) {
    let self = this;

    self.name = name;
    self.picture = picture;
    self.count = 0;

    let mainDiv = $('#cats');
    let catDiv = $('&lt;div&gt;&lt;/div&gt;');

    mainDiv.append(catDiv);

    self.img = $(`&lt;img src="${self.picture}"&gt;`);
    catDiv.append(self.img);

    self.counter = $('&lt;p&gt;&lt;/p&gt;');
    catDiv.append(self.counter);

    self.img.click(function() {
      self.count++;
      self.counter.text(`You clicked ${self.name} ${self.count} times.`);
      self.counter.css("font-size", "+=0.5");
    });
  }
}

$(document).ready(function() {
  new Cat('Kimmy', 'http://newmediarockstars.com/wp-content/uploads/2014/07/femcat.png');
  new Cat('Logan', 'http://svoctopussy.com/wp-content/uploads/2013/02/Grumpy-Cat.jpg');
});
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"&gt;&lt;/script&gt;
&lt;h1&gt;Cat Clicker&lt;/h1&gt;
&lt;div id="cats"&gt;&lt;/div&gt;




I wanted it to be dynamic, so if I want to add more cats, I just have to instance a new object of the Cat class, like it's done in the document.ready function.

The Cat constructor adds a new cat in the HTML (it appends the cats div), using div, h1, img and p. Everytime you click the img (), the p element text is updated with the click count.

I'm a complete beginner in JS. What can I refactor here to make the code more legible and idiomatic?

EDIT: In the third line, there's a let self = this;. I did that because I needed to access the Cat instance inside the img.click callback function. I don't know if that's how it's done nor how I can improve that.
In the third line, there's a let self = this;. I did that because I needed to access the Cat instance inside the img.click callback function.


Use an arrow function, which won't rebind this. The self alias can then be removed.

this.img.click = () =&gt; {
  this.count++;
  ...
}


Your examples don't save the Cats anywhere, access any properties on them, pet them, or otherwise interact with them -- if adding a cat to the DOM is all you need, the constructor doesn't need to attach anything to this (which is equivalent to exposing things as public properties).


  The Cat constructor adds a new cat in the HTML (it appends the cats div), using div, h1, img and p.


Putting that behaviour in the constructor is not ideal. People reading your code probably expect new Cat(...) to return a cat, but not necessarily for it to put that cat somewhere. Besides being unexpected, this isn't very flexible: what if I want to put a cat somewhere else on the page?

It's probably better to separate creating the cat (and its click handler) from actually attaching it anywhere. You could add another method in the Cat class, like this:

  attach(element) {
    element.append(this.catDiv);
  }


but I think all you need in this example is a function:

function createCat(name, picture) {
  let clickCount = 0;

  const $cat = $('&lt;div/&gt;');    // $var is just a naming convention for jQuery variables
  const $img = $('&lt;img/&gt;', { src: picture }).appendTo($cat);
  const $counter = $('&lt;p/&gt;').appendTo($cat);

  $img.click(() =&gt; {
    clickCount++;
    $counter
      .text(`You clicked ${name} ${clickCount} times.`)
      .css("font-size", "+=0.5");    // Most jQuery methods can be chained
  });

  return $cat;    // return the cat div, not yet attached to the DOM
}


$(function() {    // equivalent to $(document).ready(function() {
  const $main = $('#cats');

  $main.append(createCat('Kimmy', 'http://newmediarockstars.com/wp-content/uploads/2014/07/femcat.png'));
  $main.append(createCat('Logan', 'http://svoctopussy.com/wp-content/uploads/2013/02/Grumpy-Cat.jpg'));
});