DEV Community

K
K

Posted on

Classes in JavaScript

When you started programming JavaScript years ago, you probably learned that it doesn't have classes, but prototypes! So you looked into your OOP courses from university and try to find something about this and the only thin your professor has to say about it is that nobody uses prototype based object orientation anyway and you are good to go with class based object orientation.

So, you learn that JavaScript is one of the most used programming languages on the planet and got your first job coding it, but now your knowledge is worth nothing?

Many years this was kinda true.

But...!

With the release of ES6, aka ES2015, classes are part of JavaScript and don't need to mind the prototypes anymore.

What does this mean?

Well, classes in JavaScript are basically syntactic sugar for the whole prototype based OOP stuff and the first releases (like ES2015) only include the very basics. Some things you may know from class based languages won't work out of the box.

So what works with ES2015?

// You can create a class like this
class A {}

// But also like that
const A = class {};
let A = class {};

// It can even be anonymous if you export it from a module
export default class {}

// Your class can also have methods and static methods
class A {
  static doAnything() {
    console.log(this, "== undefined");
  }

  doSomething() {
    console.log("I'm doing something with ", this);
  }
}

// You can also use inheritance, with calls to the parent class
class B extends A {
  constructor() {
    super();
  }
}
Enter fullscreen mode Exit fullscreen mode

This isn't much, but it gives you the basis of class based OOP and in the background it fiddles around with prototypes, so you don't have to worry.

So, what do you want that may be missing?

Class fields are a basic feature of many languages, but not directly part of JS classes. So the following won't work with ES2015.

class A {
  x: 10; // Error
}
Enter fullscreen mode Exit fullscreen mode

You have to define them inside the constructor on creation time.

class A {
  constructor() {
    this.x = 10;
  }
}
Enter fullscreen mode Exit fullscreen mode

There is a proposal to add them in ES2018, they look a bit different tho.

class A {
  x = 10;
}
Enter fullscreen mode Exit fullscreen mode

Bound methods are the default behaviour in many languages, but the methods of JS classes aren't bound by default. This means, when you pass around methods as callbacks, the object they correspond to can go missing.

class A {
  constructor(x) { this.x = x; }
  publicMethod() { return this.x; }
}

const a = new A(10);
const callback = a.publicMethod;
callback(); // Error
Enter fullscreen mode Exit fullscreen mode

This can be fixed by manual binding a method to this in the constructor.

class A {
  constructor(x) {
    this.x = x;
    this.publicMethod = this.publicMethod.bind(this);
  }
  publicMethod() { return this.x; }
}

const a = new A(10);
const callback = a.publicMethod;
callback(); // 10
Enter fullscreen mode Exit fullscreen mode

In the future (ES2018) this can also be solved with class fields and arrow functions.

class A {
  constructor(x) { this.x = x; }

  // a class field that holds a method
  publicMethod = () => { return this.x; };
}

const a = new A(10);
const callback = a.publicMethod;
callback(); // 10
Enter fullscreen mode Exit fullscreen mode

This works because arrow functions capture the context (this) of their enclosing scope and inside the {} of a function definition the scope is the instances of the class.

Conclusion

Class based programming gets more and more features every ECMAScript release so it's worth to build on that foundation if you don't like prototypes.

Currently they aren't as complete as they could be, but there is enough to get started.

Top comments (3)

Collapse
 
vladirien profile image
Val Fourchon

Static class methods already work with ES2015 as it is possible to see here : developer.mozilla.org/fr/docs/Web/...

Collapse
 
kayis profile image
K

Cool, thank you for the info!

Collapse
 
kayis profile image
K

Fixed.

Don't know how I missed this :)