Tutorial

Understanding Classes in JavaScript

A clear, original guide explaining JavaScript classes (ES6), how they map to prototypes, constructor usage, methods on prototype, and inheritance with extends and super.

Drake Nguyen

Founder · System Architect

3 min read
Understanding Classes in JavaScript
Understanding Classes in JavaScript

Introduction

JavaScript classes provide a readable, standardized way to create object blueprints while still relying on the languages prototype-based mechanics. Introduced in ECMAScript 2015 (ES6), the class syntax makes it easier to express concepts like constructors, methods, and inheritance without changing the underlying prototypal model. This article explains how JavaScript classes work, how they map to constructor functions and prototypes, and when to use them.

Classes Are Functions

Under the hood, an ES6 class is a special type of function. Declaring a class creates a constructor function and sets up a prototype chain for instances. You can inspect an object's prototype with Object.getPrototypeOf() and create instances with the new keyword just as you would with constructor functions.

// A function expression
const Fn = function() { }

// A class expression (ES6)
const C = class { }

console.log(Object.getPrototypeOf(Fn)); // function prototype
console.log(Object.getPrototypeOf(C));  // function prototype

Both patterns result in callable constructors. The difference is mostly syntactic: the class keyword provides clearer intent ("this is a blueprint"), but the prototype chain and instance creation remain the same.

Defining a Class and Constructor

When writing a JavaScript class, you place initialization logic inside a constructor method. This method acts like the old constructor function but is more explicit and concise.

class Hero {
  constructor(name, level) {
    this.name = name
    this.level = level
  }
}

const alice = new Hero('Alice', 5)
console.log(alice) // Hero { name: 'Alice', level: 5 }

Searchers looking for "class constructor JavaScript" or "JavaScript class constructor and methods example" will find that putting initialization in constructor() is the standard pattern for ES6 classes.

Defining Methods and Prototype Behavior

Methods declared inside a class body are added to the classs prototype, not copied to each instance. This is important for memory efficiency and follows how prototype-based inheritance works in JavaScript.

class Hero {
  constructor(name) { this.name = name }
  greet() { return `${this.name} says hello.` }
}

const h = new Hero('Varg')
console.log(h.greet()) // "Varg says hello."

// The greet method lives on the prototype
console.log(Object.getPrototypeOf(h).greet === Hero.prototype.greet) // true

Understanding "prototype vs class" is mainly about recognizing that class syntax is syntactic sugar: methods live on prototype, and the prototype chain still determines property lookup.

Extending a Class (Inheritance)

ES6 classes include extends and super to express inheritance clearly. Using these keywords ensures the prototype chain is linked and the parent constructor is called properly.

class Hero {
  constructor(name, level) {
    this.name = name
    this.level = level
  }
  greet() { return `${this.name} says hello.` }
}

class Mage extends Hero {
  constructor(name, level, spell) {
    super(name, level) // call parent constructor
    this.spell = spell
  }
  cast() { return `${this.name} casts ${this.spell}` }
}

const merlin = new Mage('Merlin', 10, 'Fireball')
console.log(merlin.greet()) // inherited method
console.log(merlin.cast())  // own method

For developers searching "JavaScript class inheritance extends super" or "JavaScript class extends super example", this pattern demonstrates safe and idiomatic inheritance while preserving prototypal semantics.

Prototype vs Class — When to Use Which

Are JavaScript classes just syntactic sugar? In large part, yes: classes present a clearer API for many developers and align with object-oriented patterns found in other languages. However, constructor functions and direct prototype manipulation can still be useful for low-level control or polyfills.

  • Use ES6 classes when you want readable, maintainable code and straightforward inheritance.
  • Use constructor functions or direct prototype assignments if you need nuanced control over prototypes, or to support legacy environments without transpilation.

Search phrases like "JavaScript prototypal inheritance vs class syntax" and "JavaScript class vs constructor function" reflect this trade-off between clarity and explicitness.

Additional Notes and Tips

  • Class methods are non-enumerable by default; they appear on the prototype, which improves performance for many instances.
  • If you need to access a classs prototype at runtime, use Object.getPrototypeOf() or Object.prototype.isPrototypeOf().
  • Remember to call super() in a derived class constructor before using this.

Conclusion

JavaScript classes give developers a clear and modern syntax for creating constructors, methods, and inheritance while retaining the languages prototype-based foundation. Whether you search for "how to use classes in JavaScript" or the "difference between prototype and class in JavaScript", mastering both class syntax and prototypal concepts will make you a stronger JavaScript developer.

Tip: When in doubt, prefer readable ES6 class syntax for application-level code and reserve prototype-level manipulation for specialized scenarios or performance-critical optimizations.

Stay updated with Netalith

Get coding resources, product updates, and special offers directly in your inbox.