Skip to content

JavaScript Tutorial Prototypes

Class Syntax vs Prototypes

Lesson 200 of 258 2 min read By Deepak Paswan Updated Oct 4, 2026

JavaScript has classes, but it is still a prototype-based language. The class keyword is a cleaner way to write what the language was already doing. It does not replace the prototype system.

The same thing, two ways

script.js
JS
// The old way
function PersonOld(name) {
  this.name = name;
}
PersonOld.prototype.greet = function () {
  return "Hi " + this.name;
};

// The class way
class PersonNew {
  constructor(name) {
    this.name = name;
  }
  greet() {
    return "Hi " + this.name;
  }
}

console.log(new PersonOld("Maya").greet()); // → Hi Maya
console.log(new PersonNew("Maya").greet()); // → Hi Maya

console.log(typeof PersonNew);                                         // → function
console.log(typeof PersonNew.prototype.greet);                         // → function
console.log(Object.getPrototypeOf(new PersonNew("x")) === PersonNew.prototype); // → true

A class is a function. Its methods are stored on ClassName.prototype, exactly as in the old style.

So what does class add?

Classes are not just “make-up”. They fix several problems:

FeatureConstructor functionClass
Calling without newsilently wrongthrows an error
Methodsenumerable propertiesnon-enumerable (cleaner for...in)
Inheritancemanual and fiddlyextends and super
Strict modeoptionalalways
Private fields (#x)not availableyes
Hoistingthe function is hoistednot usable before the declaration
static, getters/settersmanualbuilt in

Inheritance maps to the prototype chain

script.js
JS
class Animal { speak() { return "sound"; } }
class Dog extends Animal {}

const rex = new Dog();

console.log(Object.getPrototypeOf(rex) === Dog.prototype);            // → true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // → true
code
TEXT
rex  →  Dog.prototype  →  Animal.prototype  →  Object.prototype  →  null

extends simply wires up this chain for you.

What this means in practice

  • You can use classes without thinking about prototypes most of the time.
  • When something behaves strangely (a lost this, a method that shows up in odd places, instanceof results), the prototype model explains why.
  • Libraries that predate classes, and a lot of existing code, use constructor functions. You can read both.
  • You can still mix styles. A class instance is an ordinary object with a prototype, so Object.create, Object.getPrototypeOf and friends work on it.

Methods on the prototype are shared

script.js
JS
class Counter {
  count = 0;
  increment() { this.count++; }
}

const a = new Counter();
const b = new Counter();

console.log(a.increment === b.increment); // → true   (one method, on the prototype)
console.log(Object.hasOwn(a, "count"));   // → true   (the field is per instance)
console.log(Object.hasOwn(a, "increment")); // → false

Fields (data) belong to each instance. Methods are shared on the prototype. An arrow function assigned to a field is not shared: each instance gets its own copy.

lightbulb
The honest summary
Classes are syntax over prototypes. Use whichever reads better, and know that underneath it is always the prototype chain.