What is Prototype Inheritance in JavaScript?
Amit Kumar
Transforming Connections: LinkedIn's Software Heroes Shaping Tomorrow's Networks.
Overview
Prototype inheritance in javascript is the linking of prototypes of a parent object to a child object to share and utilize the properties of a parent class using a child class.
Prototypes are hidden objects that are used to share the properties and methods of a parent class with child classes.
Syntax
The syntax used for prototype inheritance has the proto property which is used to access the prototype of the child. The syntax to perform a prototype inheritance is as follows :
child.__proto__ = parent;
Example
// Creating a parent object as a prototype
const parent = {
greet: function() {
console.log(`Hello from the parent`);
}
};
// Creating a child object
const child = {
name: 'Child Object'
};
// Performing prototype inheritance
child.__proto__ = parent;
// Accessing the method from the parent prototype
child.greet(); // Outputs: Hello from the parent
In this example, parent is the parent object acting as the prototype, and child is the child object that inherits from the parent prototype using the __proto__ property. This allows the child object to access the greet method defined in the parent object directly.
While the __proto__ property can be used to perform prototype inheritance, it's important to note that directly manipulating __proto__ is not recommended in production code. Instead, the Object.create method or constructor functions with prototype are typically used for setting up prototype chains in a safer and more maintainable way.
Cons Of Prototypical Inheritance
Properties And Methods
Properties:
// Example of properties in a prototype object
const animal = {
type: "Unknown",
sound: "Undefined"
};
Methods:
// Example of a method in a prototype object
const animal = {
makeSound: function() {
console.log(`The ${this.type} makes a ${this.sound} sound.`);
}
};
Object.create
Object.create is a method in JavaScript that creates a new object with the specified prototype object and properties. It allows you to create an object that inherits from a prototype without the need to define a constructor function. This method is commonly used to set up the prototype chain for objects, enabling prototype-based inheritance.
The syntax for Object.create is as follows:
Object.create(proto, [propertiesObject]);
- proto: This parameter is the prototype object that the newly created object will inherit from.
- propertiesObject (optional): This parameter is an object that specifies additional properties for the newly created object. These properties are added to the newly created object and override properties with the same name in the prototype chain.
Here's an example demonstrating how to use Object.create:
// Creating a prototype object
const personPrototype = {
introduce: function() {
console.log(`Hi, my name is ${this.name} and I am ${this.age} years old.`);
}
};
// Creating a new object that inherits from the personPrototype
const john = Object.create(personPrototype);
john.name = 'John';
john.age = 30;
// Calling the introduce method on the john object
john.introduce();
// Outputs: Hi, my name is John and I am 30 years old.
In this example, john is a new object created using Object.create, with personPrototype as its prototype. The john object inherits the introduce method from personPrototype and defines its own name and age properties.
Object.prototype.constructor
Object.prototype.constructor is a property that refers to the constructor function that created the instance of the object.
When an object is created using a constructor function or a class, the constructor property is automatically set on the object's prototype.
Here is an example that illustrates the use of Object.prototype.constructor:
// Constructor function for creating Person objects
function Person(name, age) {
this.name = name;
this.age = age;
}
// Creating an instance of the Person object
const person = new Person('John', 30);
// Accessing the constructor property of the prototype
console.log(person.constructor);
// Outputs: ? Person(name, age) { this.name = name; this.age = age;}
In this example, the Person constructor function is used to create an instance of the Person object called person. When we access the constructor property of the person object, it refers to the Person constructor function itself.
The constructor property is often used to check the type of an object and is frequently utilized in JavaScript's prototype-based inheritance to create new instances of the same type.
hasOwnProperty
The hasOwnProperty method in JavaScript is used to check whether an object has a specific property as its own property and not inherited from its prototype chain.
It returns a boolean value indicating whether the object has the specified property.
The syntax for hasOwnProperty is as follows:
object.hasOwnProperty(propertyName)
Here is an example of using the hasOwnProperty method:
const car = {
make: 'Toyota',
model: 'Corolla'
};
console.log(car.hasOwnProperty('make')); // Outputs: true
console.log(car.hasOwnProperty('model')); // Outputs: true
console.log(car.hasOwnProperty('year')); // Outputs: false
In this example, the car object has the properties make and model. Calling the hasOwnProperty method checks if the object has these properties directly. It returns true for existing properties and false for non-existing properties.
hasOwnProperty is commonly used in JavaScript to distinguish between an object's own properties and those inherited from its prototype chain, ensuring that the property being checked exists directly on the object.
The prototype chain
let student = {
id: 1,
};
let tution = {
id: 2,
};
let school = {
id: 3,
};
student.__proto__ = school; //level1 inheritance
student.__proto__.__proto__ = tution; //level2 inheritance
console.log(student.id); //the student object's property
console.log(student.__proto__.id); //school object's property
The structure of stdent object will be,
id: 1
[[Prototype]]: Object
id: 2
[[Prototype]]: Object
id: 3
[[Prototype]]: Object
The output will be based on hierarchy:
1
2
In this example, the child object is created with parent as its prototype using Object.create. When accessing properties of the child object, if the property is not found directly on the child object, JavaScript looks for it in the parent object due to the prototype chain.
Understanding the prototype chain is crucial for comprehending how inheritance works in JavaScript and is essential for creating efficient and maintainable code using prototype-based inheritance.
Setting Up Prototypical Relationships
A prototypical relationship can be created by performing prototype inheritance. The objects involved in the prototypical relationship are called child and parent.
The child is the object which inherits the properties of the parent object. Let us consider the following example in which the prototype relation is made using the proto prroperty.
let baseuser = {
read: true,
};
let developer = {
write: true,
};
developer.__proto__ = baseuser;
console.log(developer.read); //true
From the example, we can see that the inherited class or the child class can access the properties of the parent class.
Inheriting Methods
The prototype inheritance not only inherits the properties of the object, it also inherits the methods of the object. We can define a function in the parent class and call the function using the child class. We can also add a getter and setter method to the parent class which can be used by the child class.
For example:
let baseuser = {
//parent object
read: true,
job: "",
showreadpermission: function () {
console.log(this.read);
},
//setter method to set the job of user
set detail(value) {
this.job = value;
},
//getter method to get job detail
get detail() {
return `${this.job}`;
},
};
let developer = {
//child object
write: true,
};
developer.__proto__ = baseuser;
developer.showreadpermission(); //calling parent function
developer.detail = "blogger"; //calling setter method
console.log(developer.detail); //calling getter method
Output:
true
blogger
The getter and setter method in the above code represented by the syntax,
set name(parameter){
this.property=parameter;
},
object.name=parameter; //calling setter function
get name(){
//display the properties
}
object.name; //calling getter function.
These methods are used to set the value to the properties of the object and also print the values that are currently set to the properties of the object. Using these kinds of getter and setter we can easily modify and display the properties of the parent object.
In our example, the child object is developer and the parent object is base user.
Multi-Tier Inheritance With Scalability
let subject = {
topic: "javascript",
about: function () {
console.log("JS is amazing");
},
}; //base class
let course = {
__proto__: subject,
instructor: "professor",
}; //inherited from subject
let department = {
__proto__: course,
dept_name: "IT",
}; //inhserited from course
let student = {
__proto__: department,
id: 1,
}; // inherited from department
console.log(student.dept_name);
The output will be IT. This way of approach makes inheritance more efficient and simple.
Objects Inherit From Objects
Function Prototypes
Consider the simple example,
const course = function () {}; //adding prototype directly
course.prototype.name = "javascript";
const student = new course();
student.id = 1; //adding property
console.log(student);
Output:
id: 1
[[Prototype]]: Object
name: "javascript"
constructor: ? ()
[[Prototype]]: Object
We can see that the prototype has been modified and the student also has a unique value called id.
The arrow function in javascript doesn't have a default prototype.
Differential Inheritance
In prototype inheritance, when using the Object.prototype method to assign properties to a prototype, the properties are not actually copied from parent to child but they are just linked with each other. This model is called Differential Inheritance in javascript and is more often referred to as prototype chain.
We can verify this using the hasOwnProperty() method. Let us consider the example of the above section here and check for the name property.
console.log(student.hasOwnProperty("name"));
console.log(student.hasOwnProperty("id"));
Output:
false
true
Since student has its own property called id we get true and since only the prototype has the property called name we get false.
Standard Way To Implement Prototypal Inheritance In ES5
The ES5 introduced two differnd mthods such as Object.create() and Object.getPrototypeOf().
Object.create(object, { newObjectproperties });
Let us consider a simple example to understand this further.
let package = {
version: "2.0",
};
let application = Object.create(package, {
name: { value: "game" },
}); // inherited from package
console.log(application);
console.log(Object.getPrototypeOf(application));
This has the following output which only shows the prototype object:
//application object
{name: 'game'}
name: "game"
[[Prototype]]: Object
version: "2.0"
[[Prototype]]: Object
// prototype of application object
version: "2.0"
[[Prototype]]: Object
Extending The Prototype Chain
Every object has a prototype object which can be accessed by Object.prototype property. By using this we can extend a prototype chain.
New initialization
The prototype of a function object can't be directly modified. So we use a function object to assign the prototype of a function to another function object.
function first() {}
first.prototype.value = 2;
function second() {}
second.prototype = first; //second inherits from first
const final = new second();
console.log(final);
The output denotes the structure of inheritance:
[[Prototype]]: ? first()
arguments: null
caller: null
length: 0
name: "first"
prototype: {value: 2, constructor: ?}
[[FunctionLocation]]: VM1329:1
[[Prototype]]: ? ()
Object.setPrototypeOf
This method can be used to set the prototype for any object using another object's prototype.
The syntax is:
Object.setPrototypeOf(object, prototype);
Let us perform the above example using this method.
function first() {}
first.prototype.value = 2;
function second() {}
//making second inherit first
Object.setPrototypeOf(second, first.prototype);
const final = new second();
console.log(final);
The simplified output will be as follows:
[[Prototype]]: Object
[[Prototype]]: Object
value: 2
constructor: ? first()
This output has a separate prototype object for the first as it copies the prototype of the first into the second object.
Prototype And Object.getPrototypeOf
The Object.getPrototypeOf() is used to get the prototype of a object specified in the parameter.
Syntax :
Object.getPrototypeOf(object);
For example :
let one = {
value: 1,
};
let two = {
value: 2,
__proto__: one,
};
// inherited from package
console.log(two);
console.log(Object.getPrototypeOf(two));
The above example has an object two which is extended from object one using the method of chain linking and the getPrototypeOf() method is used to get the prototype of object two.
// the object two
{value: 2}
value: 2
[[Prototype]]: Object
value: 1
[[Prototype]]: Object
// prototype of the object two
{value: 1}
value: 1
[[Prototype]]: Object
Conclusion
5? @CodeChef (max. 2028) | Knight (top 1.38%) @Leetcode (max. 2153) Solved(1000+) | Specialist @Codeforces (max. 1563) | Competitive Programmer | Java , C++ | FrontEnd(Html ,CSS, JavaScript,React Js, TypeScript, Next Js)
1 个月Thanks for Sharing