- JS Introduction
- JS Introduction
- JS Comments
- JS Variables
- JS Datatypes
- JS Operators
- JS Type Conversions
- JS Control Flow
- JS Comparisons
- JS If else
- JS If else Ladder
- JS Ternary Operator
- JS Switch
- JS For Loop
- JS For In
- JS For Of
- JS While
- JS Do While
- JS Break & Continue
- JS Functions
- JS Function Declaration
- JS Function Parameters
- JS Return Statement
- JS Function Expressions
- JS Anonymous Functions
- JS Objects
- JS Objects
- JS Object Methods
- JS Object Constructors
- JS Object Destructuring
- JS Object Prototypes
- JS Map, Filter & Reduce
- JS ES6
- JS ES6
- JS let and const
- JS Arrow Functions
- JS Template Literals
- Destructuring Assignment
- JS Spread Operator
- JS Default Parameters
- JS Classes
- JS Inheritance
- JS Map
- JS Set
- JS Async
- JS Callbacks
- JS Asynchronous
- JS Promises
- JS Async/Await
- JS HTML DOM/BOM
- JS Document Object
- JS getElementbyId
- getElementsByClassName
- JS getElementsByName
- getElementsByTagName
- JS innerHTML
- JS outerHTML
- JS Window Object
- JS History Object
- JS Navigator Object
- JS Screen Object
JavaScript Object Prototypes
- Object prototypes are the primary mechanism JavaScript uses to handle inheritance, allowing multiple objects to share properties and methods efficiently.
- Every object in JavaScript has an internal link to another object called its prototype. These linked objects form a "chain" that JavaScript traverses to find the data it needs.
Prototypes are why you can use methods like .toString() or .hasOwnProperty() on an object you just created, even if you didn't define those methods yourself. They are inherited from the base Object.prototype.
Prototype Chain:
- When you try to access a property (like
user.name) or a method (likeuser.login()), the JavaScript engine first looks at the object itself. - If the property isn't found, it looks at the object's prototype. If it’s still not there, it looks at the prototype's prototype.
- This search continues until the property is found or the chain ends at
null. This sequence is what we call the prototype chain.
Setting a Prototype: The Object.create() method is a clean and modern way to create a new object while explicitly choosing which object should serve as its prototype.
// A base "Template" or Prototype Object
const personPrototype = {
greet: function() {
console.log(`Hello, my name is ${this.name}!`);
}
};
// Creating a specific object that "inherits" from personPrototype
const person = Object.create(personPrototype);
// Assigning unique data to this specific instance
person.name = "Alex";
// Accessing the method defined on the prototype
person.greet(); // Output: Hello, my name is Alex!
prototype property (found on functions) with the internal [[Prototype]] (accessed via Object.getPrototypeOf()) found on instances. Only functions have a .prototype property that you can modify to set up inheritance for future instances.
Constructor Functions: Before modern Classes (ES6) were introduced, constructor functions were the standard way to create multiple similar objects with shared prototype methods.
// Constructor Function (The Blueprint)
function Person(name, age) {
this.name = name;
this.age = age;
}
// Adding a method to the prototype so all "Person" instances share it
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}!`);
};
// Creating Instances using the 'new' keyword
const person1 = new Person('John', 30);
const person2 = new Person('Alice', 25);
// Both objects use the same greet() function from the prototype
person1.greet(); // Output: Hello, my name is John!
person2.greet(); // Output: Hello, my name is Alice!
new keyword when calling a constructor function, this will refer to the global object (or undefined in strict mode), which can lead to hard-to-debug errors and global variable pollution.
Checking Prototypes: The instanceof operator is a handy tool to verify the lineage of an object. It checks if a constructor's prototype exists anywhere in the object's prototype chain.
console.log(person1 instanceof Person); // Output: true
console.log(person1 instanceof Object); // Output: true (because Person inherits from Object)
Changing Prototypes: While possible, you should generally avoid changing an object's prototype after it has been created. However, Object.setPrototypeOf() is the built-in method to do so.
const animal = {
sound: function() {
console.log('Generic animal sound');
}
};
const dog = {
breed: 'Labrador'
};
// Setting the Prototype of 'dog' to 'animal' dynamically
Object.setPrototypeOf(dog, animal);
// Now 'dog' can access 'sound'
dog.sound(); // Output: Generic animal sound
Object.setPrototypeOf() is a very slow operation in modern JavaScript engines. It interferes with how browsers optimize code and can lead to significant performance drops in your application.
Summary
- Efficiency: Prototypes allow objects to share methods, saving memory by not duplicating functions for every instance.
- The Chain: JavaScript searches up the prototype chain until it finds a property or hits the end (null).
- Inheritance:
Object.create()and constructor functions are the standard ways to implement prototype-based inheritance. - Performance: Avoid modifying prototypes of existing objects at runtime; instead, define your structure clearly during object creation.