So as I learn more about the Prototypal Inheritance
in JS, I read the following in MDN article (read lines just above this link)
Note that when we are calling our constructor function, we are defining greeting() every time, which isn't ideal. To avoid this, we can define functions on the prototype instead, which we will look at later.
The idea recommended is to add properties
on Function and methods
on the prototype
(read here)
Person.prototype.farewell = function() {
alert(this.name.first + ' has left the building. Bye for now!');
};
I read at multiple places that this way
The object creation is faster, since the farewell
is not created for every object creation. This is because it is created once and attached to the prototype
, and all the objects link to the prototype
.
The methods are looked up on the prototypal chain
so every object links to the same method on the prototype
.
Now comes the ES6 class. I have the following code
class Person {
constructor(first, last, age, gender, interests) {
this.name = {
first: first,
last: last
};
this.age = age;
this.gender = gender;
this.interests = interests;
}
greeting () {
console.log("Hi! I am", this.name.first);
}
farewell () {
console.log(this.name.first, "has left the building. Bye for now!");
}
}
It seems that with this approach greeting
and farewell
will be created again (following up on same logic as Functions since class
is a syntactic sugar)
So, I changed the class to
class Person {
constructor(first, last, age, gender, interests) {
this.name = {
first: first,
last: last
};
this.age = age;
this.gender = gender;
this.interests = interests;
}
}
Person.prototype.greeting = function () {
console.log("Hi! I am", this.name.first);
}
Person.prototype.farewell = function () {
console.log(this.name.first, "has left the building. Bye for now!");
}
Question
1. Does the latter way (Adding methods on prototype
in ES6 class
) is a recommended way?
2. Does the logic of class
and traditional new Function
to create a new object align? Copy
vs Method on Prototype
?
Please let me know if there is anything else I am missing
Thanks
UPDATE
After few answers, I retried my examples and confirmed the answers. My code looks like
class Phone {
constructor(company, name, color, price) {
this.company = company;
this.name = name;
this.color = color;
this.price = price;
}
print() {
console.log(this.company, this.name, this.color, this.price);
}
}
class Apple extends Phone {
constructor(name, color, price) {
super("Apple", name, color, price);
this.companyWork = "ClosedSource";
}
}
let iPhone11 = new Apple("iPhone11", "black", 900);
iPhone11.print()
After I ran this code, I can confirm that print()
is available on Phone.prototype
As you've already discovered, class
definitions put methods on the prototype. You asked for a reference so here's a little code you can run to see for yourself:
class Person {
constructor(first, last, age, gender, interests) {
this.name = {
first: first,
last: last
};
this.age = age;
this.gender = gender;
this.interests = interests;
}
greeting () {
console.log("Hi! I am", this.name.first);
}
farewell () {
console.log(this.name.first, "has left the building. Bye for now!");
}
}
let p = new Person("Jack", "Beanstalk", 201, "giant", ["crushing things", "stomping things"]);
console.log("Person", Object.getOwnPropertyNames(Person));
console.log("p", Object.getOwnPropertyNames(p));
let p_prototype = Object.getPrototypeOf(p);
console.log("p_prototype === Person.prototype is ", p_prototype === Person.prototype);
console.log("Person.prototype", Object.getOwnPropertyNames(Person.prototype));
That generates this output:
Person [ 'length', 'prototype', 'name' ]
p [ 'name', 'age', 'gender', 'interests' ]
p_prototype === Person.prototype is true
Person.prototype [ 'constructor', 'greeting', 'farewell' ]
So, you can draw these conclusions:
The Person
class has only the expected properties for a constructor function and the prototype object, none of the class-defined methods are there.
An instance of the class has only the expected data properties that are assigned in the constructor, none of the class-defined methods are on the object itself.
The prototype you get from an instance is the same as the prototype of the class (thus no new object is created for each instance).
The Person.prototype
has the expected methods from the class
definition on it plus a property that points to the constructor itself (used in inheriting and calling derived constructor).
So, you can verify from this that methods defined with the class
syntax go on the Classname.prototype
object and that object is shared with all instances.