Skip to main content

Command Palette

Search for a command to run...

Prototype — The Backbone of JavaScript Objects

Updated
•8 min read•View as Markdown
Prototype — The Backbone of JavaScript Objects
S

Software Developer | Freelancer

Objects

Objects is a data structure

It is a way to store data in memory in Key Value Pair form

Objects → Properties, Methods[Functionalities]

  • Properties → Attribute: Color, weight etc.

- Method → Actions, functions

Creation

  1. Using Object Literals
const person = {    // non singleton Object
  id: '1',
  firstname: "Sandeep",
  lastname: "Patel",
  techStack: ["HTML", "CSS", "JS"],
  student: true,
  getFullName: function () {
    return this.firstname + " " + this.lastname;
  },
  address: {
    city: "Pune",
    state: "Maharashtra",
    country: "India"
  }
};
  1. Using the Object Constructor
const person = new Object();   // singleton Object
person.name = "John";
person.age = 25;
  1. Using Object.create()

create a new object with a specified prototype. It allows you to set up prototype inheritance cleanly.

// Syntax

Object.create(proto, propertiesObject[Optional)
  • proto: The object to be used as the prototype.

  • propertiesObject (optional): An object defining additional properties.

// Define an object 'person' with a method 'greet'
const person = {
  greet: function () {
    console.log(`Hello, my name is ${this.name}`);
  },
};

// Create a new object 'john' that inherits[Extends] from 'person'
const john = Object.create(person);

// Add a 'name' property to 'john'
john.name = "John";

// Call the 'greet' method, which is inherited from 'person'
john.greet(); // Output: Hello, my name is John
  1. Using a Constructor Function
// Constructor function for a Person
function Person(name) {
  this.name = name;
}

// Adding a method to the prototype
Person.prototype.greet = function () {
  console.log(`Hello, my name is ${this.name}`);
};

// Creating instances
const john = new Person("John");
const jane = new Person("Jane");

// Calling methods
john.greet(); // Output: Hello, my name is John
jane.greet(); // Output: Hello, my name is Jane
  1. Using ES6 Classes
// Define a Person class
class Person {
  constructor(name) {
    this.name = name;
  }

  // Method inside the class
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

// Creating instances
const john = new Person("John");
const jane = new Person("Jane");

// Calling methods
john.greet(); // Output: Hello, my name is John
jane.greet(); // Output: Hello, my name is Jane

Accessing


console.log("Person details: ", person);
console.log("Person id: ", person.id);
console.log("Person name: ", person.firstname + " " + person.lastname);
console.log("Person techStack: ", person.techStack);
console.log("Person is student: ", person.student);
console.log("Person full name: ", person.getFullName());
console.log("Person address: ", person.address);
OUTPUT:
Person details:  {
  id: '1',
  firstname: 'Sandeep',
  lastname: 'Patel',
  techStack: [ 'HTML', 'CSS', 'JS' ],
  student: true,
  getFullName: [Function: getFullName],
  address: { city: 'Pune', state: 'Maharashtra', country: 'India' }
}
Person id:  1
Person name:  Sandeep Patel
Person techStack:  [ 'HTML', 'CSS', 'JS' ]
Person is student:  true
Person full name:  Sandeep Patel
Person address:  { city: 'Pune', state: 'Maharashtra', country: 'India' }

Adding Properties

You can add properties using dot notation (.) or bracket notation ([]).

const person = { name: "John" };

// Adding a new property
person.age = 30;
person["city"] = "New York";

console.log(person);  // Output: { name: "John", age: 30, city: "New York" }

Deleting Properties

You can delete properties using the delete keyword.

const person = { name: "John" };

// Adding a new property
person.age = 30;
person["city"] = "New York";

delete person.age;

console.log(person);  // Output: { name: "John", city: "New York" }

Memory

Stack Memory

  • Primitive types (such as number, string, boolean, null, undefined, symbol, and bigint) are stored in stack memory

  • Execution is fast because stack memory has a fixed size.

  • It follows the LIFO (Last In, First Out) principle.

  • When a function executes, its local variables are stored in the stack, and once the function execution is complete, they are removed from the stack.

--------------------------------------------------
|                  Stack Memory                  |
--------------------------------------------------
| b -> 20                                        |
| a -> 10                                        |
--------------------------------------------------

let a = 10;  // Primitive type (Stack)
let b = a;   // `b` ko `a` ka copy milta hai
b = 20;      // `b` change hota hai, but `a` same rehta hai

console.log(a); // 10
console.log(b); // 20

Heap Memory

  • Objects and reference(Non-Primitive) types (such as arrays, functions, objects, heap, graph, tree ) are stored in heap memory.

  • Heap memory has a dynamic size, which makes it slower compared to stack memory.

  • When an object is created, memory is allocated in the heap, and its reference is stored in stack memory.

  • Garbage Collector (GC) unused objects ko clean karta hai jo kisi bhi reference se accessible nahi hote in JS.

--------------------------------------------------
|                  Stack Memory                  |
--------------------------------------------------
| obj1 -> (Heap Ref: 0x1)                        |
| obj2 -> (Heap Ref: 0x1)                        |
--------------------------------------------------

--------------------------------------------------
|                  Heap Memory                   |
--------------------------------------------------
| (0x1) -> { name: "Amit" }                      |
--------------------------------------------------

let obj1 = { name: "Rahul" };  // Heap me allocate hota hai
let obj2 = obj1;  // Stack me reference copy hota hai (Heap ka address)
obj2.name = "Amit";  // Heap me change hone se dono references pe effect

console.log(obj1.name); // "Amit"
console.log(obj2.name); // "Amit"

Memory Leak

Jab program memory allocate karta hai (Heap me), par baad me us memory ko free nahi karta (ya us tak koi access nahi hai), to usko Memory Leak kehte hain.

How to Copy Objects in JS

When we want to copy an object, there are two ways

  1. Shallow Copy

  2. Deep Copy

Shallow Copy

Shallow copy sirf top-level properties copy karta hai, par agar object ke andar koi nested object ho, to wo reference copy hota hai.

Method 1: Object.assign()

let obj1 = { name: "Rahul", age: 25 };
let obj2 = Object.assign({}, obj1);

obj2.age = 30; // Change `obj2` only
console.log(obj1.age); // 25 (No effect on obj1)
console.log(obj2.age); // 30

Method 2: Spread Operator { ... }

let obj1 = { name: "Rahul", age: 25 };
let obj2 = { ...obj1 };

obj2.name = "Amit"; // Change in `obj2`
console.log(obj1.name); // "Rahul" (No effect on obj1)
console.log(obj2.name); // "Amit"

--------------------------------------------------
|                 Stack Memory                   |
--------------------------------------------------
| obj1 -> (Heap Ref: 0x1)                        |
| obj2 -> (Heap Ref: 0x1)   <-- SAME REFERENCE   |
--------------------------------------------------

--------------------------------------------------
|                 Heap Memory                    |
--------------------------------------------------
| (0x1) -> { name: "Amit", details: { age: 30 } }|
--------------------------------------------------

Deep Copy

Agar object me nested objects ho, aur unko bhi independent copy chahiye, to Deep Copy karni padegi.

Method : JSON.parse(JSON.stringify(obj))

let obj1 = { name: "Rahul", details: { age: 25, city: "Delhi" } };
let obj2 = JSON.parse(JSON.stringify(obj1));

obj2.details.age = 30; // Change in obj2
console.log(obj1.details.age); // 25 (No effect on obj1)
console.log(obj2.details.age); // 30

--------------------------------------------------
|                 Stack Memory                   |
--------------------------------------------------
| obj1 -> (Heap Ref: 0x1)                        |
| obj2 -> (Heap Ref: 0x2)   <-- NEW REFERENCE    |
--------------------------------------------------

--------------------------------------------------
|                 Heap Memory                    |
--------------------------------------------------
| (0x1) -> { name: "Rahul", details: { age: 25 } } |
| (0x2) -> { name: "Rahul", details: { age: 30 } } |
--------------------------------------------------

Prototypes

A prototype is simply an object from which other objects inherit properties.

JavaScript follows a prototype-based inheritance model → meaning that objects inherit properties and methods from other objects.

Prototype Inheritance

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name}`);
};

const person1 = new Person("Aman");

person1.greet(); // Output: Hello, my name is Aman

The Prototype Chain

When you access a property of an object, JavaScript first checks if the object has that property. If not, it looks up the prototype chain until it reaches null.

function Person(name) {
    this.name = name;
}

Person.prototype.greet = function () {
    console.log(`Hello, my name is ${this.name}`);
};

const john = new Person("John");
john.greet();  // Output: Hello, my name is John

console.log(john.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true

DRY principle - Do not repeat yourself

// Prototype Chaining

const person1 = {
  "First Name": "Sandeep",
  "Last Name": "Patel",
  getFullname: function () {
    if (this["First Name"] !== undefined) return `${this["First Name"]} ${this["Last Name"]}`;

    return this["First Name"];
  }

}

const person2 = {
  "First Name": "Amit",
  "Last Name": "Singh",
  // getFullname: function () {
  //   return `${this["First Name"]} ${this["Last Name"]}`
  // }

};

// Bad Practice: Is Internal work           
person2.__proto__ = person1;
// person1.__proto__ = null; 

// DRY principle - Do not repeat yourself

console.log("Person 1: ", person1.getFullname()); // Person 1:  Sandeep Patel
console.log("Person 2: ", person2.getFullname()); // Person 2:  Amit Singh
console.log(person2.toString()); // [object Object]

Object Prototypes

Object has an internal link (__proto__) to its prototype object.

const obj = {};
console.log(obj.__proto__ === Object.prototype); // true

// Even arrays and functions inherit from Object.prototype✅

console.log([].__proto__ === Array.prototype); // true
console.log(Array.prototype.__proto__ === Object.prototype); // true

Modifying Prototypes

✅ Do's (Safe Modifications)

  • Use Prototypes for Shared Methods
function Person(name) {
  this.name = name;
}

// Adding methods to the prototype instead of the instance
Person.prototype.greet = function() {
  return `Hello, my name is ${this.name}`;
};

const person1 = new Person("Alice");
console.log(person1.greet()); // ✅ Works efficiently
  • Use Object.create() for Prototypal Inheritance
const animal = {
  makeSound() {
    console.log("Some generic sound");
  }
};

const dog = Object.create(animal);
dog.bark = function() {
  console.log("Woof!");
};

dog.makeSound(); // ✅ Inherited from `animal`
dog.bark();      // ✅ Own property
  • Use Object.getPrototypeOf() and Object.setPrototypeOf() Instead of __proto__
const obj = { key: "value" };
console.log(Object.getPrototypeOf(obj)); // ✅ Retrieves prototype

console.log(obj.__proto__); // ❌ Deprecated and slow

❌ Don'ts (Avoid These Mistakes)

  • Don’t Modify Object.prototype (or Built-in Prototypes)
Array.prototype.removeFirst = function() {
  this.shift(); 
};

const arr = [1, 2, 3];
arr.removeFirst(); 
console.log(arr); // ❌ Works but pollutes global prototype!
  • Don’t Overwrite the Prototype Object After Instantiation
function Person(name) {
  this.name = name;
}

const person1 = new Person("Alice");

// Overwriting the prototype (BAD!)
Person.prototype = {
  greet() {
    return `Hello, my name is ${this.name}`;
  }
};

console.log(person1.greet()); // ❌ TypeError: person1.greet is not a function
  • Avoid Extending Object.prototype or Function.prototype
Object.prototype.sayHello = function() {
  return "Hello!";
};

console.log({}.sayHello()); // ❌ Pollutes all objects!

Why in JS everything is an object?

const obj = {};           // obj.__proto__ - Object
const arr = [1, 2, 3];    // arr.__proto__.__proto__ - Object
const str = "Hello";      // str.__proto__.__proto__ - Object