I am online
← Back to Articles

JavaScript Prototypes and Object.create👇

JavaScriptMay 20, 2025

In JavaScript, objects can share methods through prototypes. This avoids duplicating the same functions for every object, making code more efficient and memory-friendly. Let’s walk through different versions of how we can model a simple Player object with properties and methods.

Version 1: Direct Object

You define everything inside a single object.

let player = {};
player.name = "John Doe";
player.age = 20;
player.energy = 100;

player.run = function(speed) {
  this.energy -= speed;
  console.log(this.energy);
};

player.jump = function(height) {
  this.energy += height;
  console.log(this.energy);
};

✅ Quick to write, ❌ but not reusable for multiple players.

Version 2: Factory Function (Methods inside)

We wrap it in a function that returns an object:

function Player(name, age, energy) {
  let player = { name, age, energy };

  player.run = function(speed) {
    this.energy -= speed;
    console.log(this.energy);
  };

  return player;
}

const player1 = Player("John", 20, 100);
const player2 = Player("Yacine", 21, 100);

player1.run(20); // 80

✅ Reusable function, ❌ but each player gets its own copy of methods.

Version 3: Shared Methods Object

We extract methods into a shared object and assign them:

const playerMethods = {
  run: function(speed) {
    this.energy -= speed;
    console.log(this.energy);
  },
  jump: function(height) {
    this.energy += height;
    console.log(this.energy);
  }
};

function Player(name, age, energy) {
  let player = { name, age, energy };
  player.run = playerMethods.run;
  player.jump = playerMethods.jump;
  return player;
}

✅ Methods are reused, ❌ but assignment is manual and repetitive.

Version 4: Object.create (Prototype-like)

The cleanest approach is to use prototypes:

const playerMethods = {
  run: function(speed) {
    this.energy -= speed;
    console.log(this.energy);
  },
  jump: function(height) {
    this.energy += height;
    console.log(this.energy);
  },
  kickball: function(strength) {
    this.energy -= strength;
    console.log(this.energy);
  }
};

function Player(name, age, energy) {
  let player = Object.create(playerMethods); // prototype link
  player.name = name;
  player.age = age;
  player.energy = energy;
  return player;
}

const player1 = Player("John Doe", 20, 100);
const player2 = Player("Yacine BGM", 21, 100);

player2.run(20);  // 80
player2.jump(10); // 90

✅ Cleaner — all players share methods through the prototype object.

Version 5: Constructor + Prototype

This is the most common pattern before ES6 class. Instead of passing playerMethods, we attach methods directly to Player.prototype.

function Player(name, age, energy) {
  let player = Object.create(Player.prototype);
  player.name = name;
  player.age = age;
  player.energy = energy;
  return player;
}

// Shared methods live on Player.prototype
Player.prototype.run = function(speed) {
  this.energy -= speed;
  console.log(this.energy);
};
Player.prototype.jump = function(height) {
  this.energy += height;
  console.log(this.energy);
};
Player.prototype.kickball = function(strength) {
  this.energy -= strength;
  console.log(this.energy);
};

const p1 = Player("John Doe", 20, 100);
const p2 = Player("Yacine BGM", 21, 100);

p2.run(20); // 80
p2.jump(10); // 90

✅ Even better