JavaScript is a prototype-based language, therefore understanding the prototype object
is one of the most important concepts. I will give you a short overview of the Prototype object through various examples. Before reading this article, make sure that you have a basic understanding of the this
reference in JavaScript.
π Remember:
π Whenever you create a function using JavaScript, JavaScript engine adds a prototype property inside a function, Prototype property is basically an object (also known as Prototype object) where we can attach methods and properties in a prototype object, which enables all the other objects to inherit these methods and properties.
π There are different ways to create an object, one of the way is to create an object using function constructor.
π»
// function constructor
function Person(name, job, yearOfBirth){
this.name= name;
this.job= job;
this.yearOfBirth= yearOfBirth;
}
// this will show Person's prototype property.
console.log(Person.prototype);
π we can add a method calculateAge()
to the Prototype property in a Person
function constructor which will inherit by the different objects. See the code bellow:
function Person(name, job, yearOfBirth){
this.name= name;
this.job= job;
this.yearOfBirth= yearOfBirth;
}
Person.prototype.calculateAge= function(){
console.log('The current age is: '+(2019- this.yearOfBirth));
}
console.log(Person.prototype);
π Type the code in the browser console and see the output and that calculateAge()
method gets added to the Prototype property.
- Let's create 2 different objects which will
inherit
calculateAge()
method.
π Remember:
π When a certain method(or property) is called, it first checks inside the object but when it doesnβt find, then search moves on Objectβs prototype.
π»
function Person(name, job, yearOfBirth){
this.name= name;
this.job= job;
this.yearOfBirth= yearOfBirth;
}
// adding calculateAge() method to the Prototype property
Person.prototype.calculateAge= function(){
console.log('The current age is: '+(2019- this.yearOfBirth));
}
console.log(Person.prototype);
// creating Object Person1
let Person1= new Person('Irene', 'teacher', 1985);
console.log(Person1)
let Person2= new Person('Tim', 'Developer', 1982);
console.log(Person2)
Person1.calculateAge();
Person2.calculateAge();
β‘
ποΈ π The two Objects Person1 and Person2 were created using constructor
function Person, when we called Person1.calculateAge()
and Person2.calculateAge()
, as first it will check whether it is present inside Person1
and Person2
object, if it is not present, it will move Personβs Prototype object and prints the current age, which shows Prototype property enables other objects to inherit all the properties and methods of function constructor.
π Considering the fact that almost everything in JavaScript is an object, object oriented JavaScript code is very different from other object-capable languages.
π JavaScript objects are very different in the way they are created. There is no requirement for a class
.
βπ Object instances can be created using the new
operator:
π»
let Animal = new Object() {
// ...
}
or with a function constructor:
function Animal() {
// ...
}
π JavaScript objects are very flexible. While classic object oriented languages allow only property modification or property slots, JavaScript allows objects to modify their properties and methods;
π π JavaScript objects have both property and method slots. π€
π All JavaScript objects are created from the Object constructor: π³
π»
var Animal = function(name, canItSwim) {
this.name = name;
this.canItSwim = canItSwim;
}
π π The prototype allows us to add new methods to objects constructors, this means that the following method now exists in all instances of Animal
.
π»
Animal.prototype.doesItFly = function() {
if (this.canItSwim) {
console.log(`${this.name} can swim`);
} else {
console.log(`${this.name} has fly`);
}
};
Object instances of Animal
can be now created:
π»
// for this example consider dolphins can swim and horse cannot
let dolphin = new Animal("dolphin", true);
dolphin.doesItSwim(); // dolphin can swim
let horse = new Animal("horse", false);
horse.doesItSwim(); // horse has
π The prototype of the Animal object
is now the basis for inheritance
, the doesItSwim
method is accessible to both dolphin and horse because the prototype of Animal has this method. The prototype property is shared amongst all its instances and is accessible via the__proto__ property
of a particular instance.
π Now, because of the existence of method slots
and a common prototype instance property being shared across all instances, some very neat tricks are possible:
π»
horse.__proto__.doesItSwim = function() {
console.log(`the horse never swims`);
};
horse.doesItSwim(); // the horse never swims
dolphin.doesItSwim(); // the horse never swims
π Change one instanceβs prototype property or method, all instances of the object are affected. This means we could be deleting stuff as well. A horse tired of swimming could potentially do this:π€£ π€£ π€£
π»
delete horse.__proto__.doesItSwim
dolphin.doesItSwim();
//TypeError: dolphin.doesItSwim
// is not a function
Now no one gets to swim. π€£ π€£ π€£
This is just a funny example to show how fundamental the prototype
is to the Object system in JavaScript and how it can be quite tricky to people from other object oriented languages.
π With the ES6 syntax, JavaScript has been provided the feature to create classes.
π However, the concept of true classes does not exist in JavaScript but it is emulated through prototype and the class syntax is just syntactic sugar around it. Therefore, understanding this behavior is important to realize the convenience and limitations of ES6 classes.
With the new class syntax, Animal would be defined as:
π»
class Animal {
constructor (name, canItWalk) {
this.name = name;
this.canItWalk = canItWalk;
}
doesItSwim () {
if(this.canItSwim)
console.log(`${this.name} can swim`);
else
console.log(`${this.name} has walked`);
}
}
let horse = new Animal("horse", true);
horse.doesItWalk(); //horse can walk
π This does not mean it brings nothing new to the offer for prototype users, some pitfalls can be avoided by using ES6 classes, like making the new keyword mandatory for creating instances.
π»
let dolphin = Animal("dolphin", false);
//Output: TypeError: Class constructor Animal cannot be invoked without 'new'
π This is actually a good thing, since it prevents accessing the wrong context when using the object properties and methods, which is usually the global scope or the window object.
π When a function is created in JavaScript, the JavaScript engine adds a prototype property to the function.
π This prototype property is an object (called a prototype object) that has a constructor property by default.
π The constructor property points back to the function on which prototype object is a property.
Look at the following example:
π»
function Human(firstName, lastName) {
this.firstName = firstName,
this.lastName = lastName,
this.fullName = function() {
return this.firstName + " " + this.lastName;
}
}
var person1 = new Human("John", "Doe");
console.log(person1)
So objects in JavaScript have an internal property known as prototype.
It is simply a reference to another object and contains common attributes/properties across all instances of the object.
π An objectβs prototype attribute specifies the object from which it inherits properties.
π»
let numArray = [1,2,-8,3,-4,7];
π The Array object has a prototype Array.prototype
and the object instance, num
, inherits the properties of the Array object.
Happy Coding & Have fun!π€© π€
Top comments (0)