I am confuse bit by going through multiple website tutorials and now can't find the difference between below two statements; (Suppose Person a super class/function of Employee)
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
As i know first line show an Employee REFERENCE pointed to Person constructor. And constructor of Person was created by Object.create().
And Second is simply created a Employee constructor.
Let me know if am right as am a java programmer and found javascript is confusing.
The prototype in javascript is like classes in java. So the code:
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Means:
class Employee inherits new Person() { // meaning of first line
Employee constructor = Employee // meaning of second line
}
In classical javascript, there are no classes, instead there are constructors. And a constructor is just a regular function that you call via new myFunction() instead of myFunction().
And instead of a constructor belonging to a class, in javascript a prototype (class-like object) is a property of a constructor. And yes, functions are objects just like any other thing in javascript so they can have properties just like any other object.
Also, in javascript constructors cannot inherit from constructors (don't be silly :D ). Instead, constructors inherit from objects (strictly speaking, objects inherit from objects since the inheritance happens when you call the constructor). That's why we create an instance of the superclass object - to make it an object so we can inherit.
Technically speaking, the line Employee.prototype.constructor is not necessary. The first line is all that's needed to set up inheritance.
Related
One common aspect of object-oriented design (in most of the languages, especially Java) is that when we construct new object using constructor, all the methods and public/protected instance variables gets copied into the object. For example:
Car myCar = new Car('Corolla', '2015');
Now if Car class has goForward() or goBackward() methods, all of them will get copied to myCar object.
But this is not the case in JavaScript as long as I've studied. If this has been similar in JavaScript, myCarhad prototype that actually points to the Car prototype.
According to my understanding, this copying of data and methods is the ultimate requirement if we want to use class-inheritance as a design pattern. Is JavaScript really lacking this feature or just my understanding is vague? Does the new ES6 class-based structure brings this thing into picture?
Thanks for clarifying my concepts, I'm very confused over this as I've been doing things in Java in the past.
In Javascript, a constructor function contains a .prototype property that contains any methods defined for that object (either with direct assignment to the prototype in ES5 or with the class keyword in ES6).
Then, when you instantiate a new object with that constructor, the object is given a pointer to the prototype. When a method is called on that object, the Javascript interpreter will look first on the object itself for a property with that name and, if not found there, it will then go search the prototype chain.
So, the only thing that is "copied" to a newly created object in Javascript is a pointer to the prototype. And, this works identically in ES5 and ES6. The class syntax in ES6 is just new syntax for doing what we were manually doing already in ES5 (assigning methods to the prototype object).
In fact, you can even get the prototype if you want with Object.getPrototypeOf(). It's important to realize that the new object contains a pointer to the prototype object (not a copy). If subsequent changes are made to the prototype object, it is "live" and all instantiated objects before or after will see that change.
class Car {
constructor(brand, model) {
// initialize instance data
this.brand = brand;
this.model = model;
}
goForward() {
console.log("goForward");
}
goBackward() {
console.log("goBackward");
}
}
let c = new Car("Toyota", "Corolla");
console.log(Object.getPrototypeOf(c)); // shows the two methods goForward, goBackward
console.log(c.brand); // "Toyota"
Now if Car class has goForward() or goBackward() methods, all of them will get copied to myCar object.
The new object is given a pointer to the prototype. The methods are not copied individually.
According to my understanding, this copying of data and methods is the ultimate requirement if we want to use class-inheritance as a design pattern.
This is just not true. Inheritance does not require copying of all methods to the new object. There are actually many different ways to achieve proper inheritance. Javascript uses a prototype. C++ uses compile time binding. I don't know the internals of Java myself, but this post refers to a method table that each object in Java is given a pointer to.
Does the new ES6 class-based structure brings this thing into picture?
ES6 does not change how inheritance works internally in Javascript. ES6 just introduces the class syntax which is a different way of declaring an object constructor and methods, but it results in the same internal structure as the way we manually declared methods on the prototype in ES5.
While going over frontend master, I got little confused w/ below.
Can someone tell me if there is any difference? (in creating Object Chordate and Chordate2 and Chordate3?). HOw do they fundamentally differ??
I thought always doing newObject = new constructor is the way to build new object in javascript but this newObject.prototype = new Constructor threw me off.
Animal = function(name){this.name = name};
Animal.prototype.eats = function(){
return this.name + " is eating"
}
Chordate = function(name){this.name = name;}
Chordate.prototype = new Animal();
Chordate2 = function(name){this.name = name;}
Chordate2 = new Animal();
Chordate3 = new Animal();
-- my own answer --
Probably I need to watch more videos (as I assume they will say this is not recommended but I do understand how this works now. Here was my confusion and clarification.
Every function(which is another object) that gets created is pointed to it's own prototype(basically object)
Chordate which is already an object and has it's own prototype pointed to it's own object(prototype), this line(Chordate.prototype = new Animal();) is changing .prototype point to Animal prototype.
(which does look hacky, and I need to read and watch more).
So, based on that Chordate2's prototype is also it's own prototype and when you run new Animal on it, it just erases that and only Animal.prototype exists.
Same w/ (except Chordate3.prototype never existed) Chordate3.
Can someone please verify this for me?
That's how inheritance originally works in javascript (and even with classes, the underlying mechanism is still the same).
Basically Chordate is a subclass of Animal. In other languages we'd write:
class Chordate extends Animal {
}
In javascript constructors inherits from objects. Since Animal() is a constructor we need to convert it to an object. So in javascript we do:
Chordate.prototype = new Animal(); // extend Animal
The prototype property holds a prototype or template for how the object created by a constructor should look like. In this case the object created by Chordate should look like an Animal object. When you call new Chordate() the prototype will be copied into this and will be returned as a new instance.
Chordate2 and Chordate3 are just instances of Animal. From the code and the naming of the objects they look like confused code by someone not familiar with javascript. I'd personally expect something like chordate2 = new Chordate().
The first Chordate assignment "Chordate=function(name){this.name=name;} is assigning a constructor identical to that of Animal, and then the next line adds the Animal() constructor to the Chordate object.
Then Chordate2 starts off with a constructor assignment and then is overwritten as an Animal object with an undefined name attribute since no argument was passed to the constructor.
Finally Chordate3 is just an Animal object with an uninitialized name attribute as well.
I do feel funny about responding to my own question and putting it as an answer but as #torazaburo suggested and it would be good for me to get critic as someone who actually provides an answer(up until now, I have only asked) even if it’s wrong so here it goes:
Part of the confusion came as to what below actually is
Object.prototype
I fully understand that when function is created(Animal), it points to its own prototype(which in turn points to base Object(of it’s own prototype(this is found by going up the proto chain).
when Chordate function was created, it was pointing to it’s own
prototype. However, when Chordate.prototype = new Animal was ran, it
essentially overwrote it’s own prototype and pointed to Animal’s
prototype. Whether this is not recommended or not, I am eager to find
out why. I guess I was more focused on learning how this
Object.prototype works and what the relationship was to otherObject(in
this case Animal) being created.
When Chordate2 is ran,
1)it creates a function and have it point to it’s own prototype
2)when you run new Animal() = Chordate2, it essentially erases Chordate2 and creates a brand new object and
only prototype remains is Animal.prototype. Chordate2’s relationship to that is found through __proto__
Same concept w/ (except Chordate3.prototype never existed) Chordate3.
I'm studying prototypes right now and think that I'm almost there but I'm a bit confused on one topic.
Let's say we have:
function Animal(name, gender) {
this.name = name;
this.gender = gender;
}
function Cat(species) {
this.species = species;
}
Cat.prototype.color = null;
Cat.prototype = new Animal();
My question is, why is prototype needed at all for new properties?
Why couldn't we do:
Cat.color = null;
EDIT::
All the white blocks are from a uml diagram from another SO post. I added the orange boxes to suit this example that I've provided. Does this diagram I've added to still make sense?
My main problem I believe is that I was making the function constructors and the actual prototype objects too similar when in fact they're completely different things. One's a function and one's an object.
EDIT 2
With this diagram, I'm trying to clarify how the constructor property interacts and what it is exactly connected to, and more specifically, how it affects the use of this. Any comments on the validity would help.
Good question:
Cat.color = null; sets the color only on that one Cat, if you put it on the prototype any 'Cat' you instantiate afterwards will also contain a color property.
Lets say you have something like var tabby = new Cat('feline') with the code above it without the prototype tabby won't have a color.
"Everything in Javascript is an Object"
Ever wonder why you can use .toString() on say the number 50 without having written Number.toString = function(){....?
Because it's built-into Javascript. All Number.prototypes have the .toString method. And the list goes on for Arrays, Objects, Strings, etc.
Every time you write a Number in JS, imagine (no constructor is really called) calling a Number constructor function similar to your constructor functions for Animal & Cat.
That's what constructor functions do. They create an instance of (theirname).prototype. That's why function Animal() makes something of Animal.prototype and so on.
function Animal() and function Cat() otherwise have nothing to do with Animal.prototype and Cat.prototype. If you actually made a new Animal with new Animal() and then changed the constructor, the new Animal you just made wouldn't be updated, because it was constructed before the constructor changed.
Let's say you make a Cat "Hobbes"
Then after that, when you say Cat.prototype.color = null;, you're saying all objects of Cat.prototype should have a 'null' value for color. This will update Cats you constructed before, since now when you try to find Hobbe's color, it will spit undefined since you didn't give a color to Hobbes himself in function Cat(), but then JS will backtrack to Hobbe's Cat.prototype and find that color is actually null.
Hope that helps.
Several things to remind;
A constructor function is used to instantiate new objects. If a constructor function has variables defined with a preceding this. keyword then those will be the properties of the instantiated object. The variables defined with preceding var keyword won't be a part of the instantiated object.
The objects instantiated by a constructor function will have their prototypes assigned to the constructor function's prototype hence they have direct access to the constructor function's prototype. This means they can use (share) the properties and functions within the constructor function's prototype as if they are their own.
The prototype is very useful when you think of instantiating thousands of objects from a constructor function. The unique properties of each object such as name, id, color or whatever should be defined with a preceding this. in the constructor. Such as this.name or this.color however the functionalities that they are expected to share should be defined in the constructors prototype since obviously it would be a waste of memory to reserve a room for them within each instantiated object.
I've been reading MDN guide on Object Oriented programming with Javascript where in an example to show Inheritance, the following is mentioned:
// Create a Student.prototype object that inherits from Person.prototype.
// Note: A common error here is to use "new Person()" to create the
// Student.prototype. That's incorrect for several reasons, not least
// that we don't have anything to give Person for the "firstName"
// argument. The correct place to call Person is above, where we call
// it from Student.
Student.prototype = Object.create(Person.prototype); // See note below
I've looked into other answers as well, but they don't specifically tell what problems one will face on using Student.prototype = new Person()
One problem mentioned above concerns with passing firstName, but that's just one scenario.
Before anyone marks this as duplicate. The question here Using "Object.create" instead of "new" deals with generally using Object.create instead of constructors and not with what I'm asking.
The question here What is the reason to use the 'new' keyword at Derived.prototype = new Base deals with difference between foo() and new foo()
One answer for this question JavaScript inheritance: Object.create vs new gives one more reason:
When SomeBaseClass has a function body, this would get executed with
the new keyword. This usually is not intended - you only want to set
up the prototype chain. In some cases it even could cause serious
issues because you actually instantiate an object, whose
private-scoped variables are shared by all MyClass instances as they
inherit the same privileged methods. Other side effects are
imaginable.
So, you should generally prefer Object.create. Yet, it is not
supported in some legacy browsers; which is the reason you see the
new-approach much too frequent as it often does no (obvious) harm.
Also have a look at this answer.
Reading the above it seems it depends more on the given scenario being tackled. Is there a stringent reason for MDN saying using new SuperClass() is incorrect?
TL;DR You could use new Person to build your Student.prototype, but doing so complicates all of your constructor functions, limits their ability to detect construction errors, and requires that all constructors everywhere handle that form of use. Since it's more complicated, error-prone, and limiting, most people have gone the other way: Object.create.
The main pragmatic issue is: What if the super constructor requires arguments? Say Person requires a name:
function Person(name) {
this.name = name;
}
How am I to use new Person to create my prototype? I have no name to provide it.
Now, there are two ways to solve this:
Require that all constructors that need arguments detect that they have been called without arguments, assume they're being called to build a prototype, and handle that case correctly.
Use Object.create instead.
Here's the first way:
// NOT WHAT MOST PEOPLE DO
function Person(name) {
if (arguments.length === 0) {
return;
}
this.name = name;
}
function Student(name) {
Person.call(this, name);
}
Student.prototype = new Person;
Student.prototype.constructor = Student;
Note how Person has to detect that it's being called with no arguments, hope that that's because it's being used to create a prototype rather than for some other reason, and avoid trying to use the missing arguments.
That's error-prone and awkward, and it means that Person can't (for instance) raise an error if it doesn't receive name for the final instance construction call. It just doesn't know why it's being called, so it can't tell whether not having name is correct or not.
So most people go the other way:
// What most people do
function Person(name) {
this.name = name;
}
function Student(name) {
Person.call(this, name);
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Person doesn't have to have any special-case code in it, and is free to raise an error if it doesn't get name and needs it.
That's sufficienly ingrained now, as well, that it's baked into ES2015 (aka ES6)'s class keyword. This ES2015 code:
class Student extends Person {
constructor(name) {
super(name);
}
}
Translates fairly closely to the Object.create ES5 code above. (Not exactly, but fairly closely.)
Here I am trying to understand few concepts of inheritance in javascript.I have created person class and trying to inherit it in Customer class.
var Person = function(name) {
this.name = name;
};
Person.prototype.getName = function() {
return this.name;
};
Person.prototype.sayMyName = function() {
alert('Hello, my name is ' + this.getName());
};
var Customer = function(name) {
this.name = name;
};
Customer.prototype = new Person();
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
Every time a new object gets created ,javascript engine basically calls prototype's constructor. here I am trying to understand few things:
if Customer prototype is referring to Person object.So creation of new Customer object should contain only Person property/Method not the Customer property/Method.How Customer property get attached to the new Customer object (myCustomer)?
Am I missing some javascript concept here?
Here I am trying to understand few concepts of inheritance in javascript.I have created person class and trying to inherit it in Customer class.
Well then you sure have lost your way quickly. There are no classes in prototypal inheritance.
That's the whole point! :-)
Using .prototype and new Function() syntax isn't a very explicit way to leverage prototypal inheritance.
Consider using Object.create instead of new - this way allows you to directly say which object is supposed to be which's prototype. It's more straightforward and you're likely to grasp the idea of prototypes faster this way.
Also, if you want to have longer prototype chains, then this method will certainly be more comfortable to use.
You defined Person and Customer, and then set Customer's prototype to a Person instance. So, your chain looks like this:
myCustomer (a Customer instance)
Customer prototype (a Person instance)
Person prototype (a plain object)
Indeed, myCustomer is a Customer instance as it has Customer's prototype in its chain. It's not the same thing as a direct Person instance. The latter would not have Customer's prototype in the chain.
if Customer prototype is referring to Person object and so on creation new Customer object should contain only Person property/Method not Customer property/Method.
Yes. Your newly created Customer object inherits from the Person instance in Customer.prototype. As you have neither added properties to that prototype object, nor create properties to your instance in the Customer constructor, your customer contains only the person's properties.
How Customer property get attached to the new Customer object (myCustomer)?
Do it in the constructor function:
function Customer (){
this.customer_property = someValue;
}
This code is executed each time an instance is created via new. If you don't need that, you can just add the methods etc. to the Customer.prototype object.
Also have a look at What is the reason [not] to use the 'new' keyword here? - you should not instantiate a Person for the prototype object - why should all customers inherit its name etc? Use
function Customer(name) {
Person.call(this, name); // apply Person constructor on this instance
// for creating own properties (and privileged methodes)
// custom Customer code
}
Customer.prototype = Object.create(Person.prototype);
Customer.prototype.someMethod = … // Customer-specific prototype things
I think the confusion lies in saying "javascript engine basically calls prototype's constructor". For a new instance of your Customer, Javascript will create a new object, set the prototype to the Person object you've designated, then call your Customer constructor function to customize the object (this is the illusion of "class" in JS). There's no re-calling of the prototype constructor function. So, your fields/methods for Customer are set, in your Customer constructor.
When a customer object has a method/field referenced after construction, the javascript engine will try to find it in the fields/methods that were set via your constructor (or in code manipulating the object downstream of the constructor call). If it can't, it will look to the prototype object attached to find the method/field. In this way are both the Customer fields/methods available and the "superclass" fields/methods.