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.
Related
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.
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'm want to understand how and why are prototypes useful in Javascript. After I thought I knew what was going on, I stumbled with the fact that a prototype is just an object and can't be "shared" by many objects in the way I thought. Let me elaborate with an example:
var SpritePrototype = {
img: null,
pos_x: 0,
pos_y: 0,
draw: function(context2d) {
/*do stuff with the canvas
using "this" to refer to
the object this method is
being called on*/
},
//Some more member functions...
}
From the concept of "objects inheriting from objects" that's usually advocated with prototype-friendly Javascript, I thought I could just do:
var player = Object.create(SpritePrototype);
But it turns out this approach is flawed, because the non-function fields will be the ones from SpritePrototype, as player's prototype is exactly SpritePrototype. That means I can't create more objects from that prototype or the non-function fields will get all mixed up.
So what's the point in Object.create, and more important, what would be the correct way to achieve what I'm trying to do? That is, how can I make "player" get a copy of the fields and inherit the functions from its prototype?
Again, I'm interested in doing things the way they're intended to be. I can always simulate inheritance by hand or skip it altogether. The point of my question is to understand prototypes and how and when they are useful, especially in my specific case.
Property values on prototypes are shared initially, but stop being shared when that property on an instance is written (assigned) to. At that moment, the instance gets its own version of the property. So it is not entirely correct to say the value is "shared". It is shared only up to the point in time at which the property on the instance is assigned to.
var SpritePrototype = {
img: 'img1'
};
var sprite1 = Object.create(SpritePrototype);
var sprite2 = Object.create(SpritePrototype);
sprite1.img = 'img2'; // does NOT affect prototype or sprite2
console.log(sprite2.img);
< "img1"
When img is referenced, its value is taken from the prototype. However, when img is written to, a new property is created on the instance to hold the new value, and used from then on.
The only way to change the property value on the prototype is to do so explicitly:
SpritePrototype.img = 'img3';
This will change img for all instances which have not yet defined their own local version of img by assigning to it.
You problem is, that you had defined "static" members in terms of object oriented design. Everything in protoype section is shared between objects. Function doesn't get actually copied to newly created object, but it is called with proper "this".
You should initialize your variables in constructor, like this
function Sprite(...) {
this.img = null;
...
}
Then for subtype you should use Object.create to create a prototype to inherit its methods, so
Player.prototype = Object.create(Sprite.prototype);
And finally, you may call parent constructor to initialize the variables
function Player(...) {
Sprite.call(this, ...);
}
PS. Constructor should be before Player.prototype assigning.
PPS. For more info see this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
This question already has answers here:
Why is JavaScript prototype property undefined on new objects?
(5 answers)
Closed 7 years ago.
I am trying to understand the JavaScript prototype and I am bit confused.There are tons of tutorials out there and each has different explanation on it. So I don't know where to start with.
So far I have created a simple JavaScript object
var a = {flag : 1}
In MDN, I read that
All objects in JavaScript are descended from Object
But I couldn't find the prototype for this object a a.prototype gives me undefined
Then I found the prototype is available in a.constructor.prototype. When I create a function var myfunc = function() {} and then myfunc.prototype is available. So the prototype property is directly available on functions and not on objects.
Please help me to understand this and what is that a.constructor.
Any help is greatly appreciated.
Every function can be called as a constructor (with new keyword).
function Dog() {
this.legs = 4;
}
When you call it as a normal function, var dog = Dog(), it will define window.legs in browsers to be 4 (something a bit different but related if in Node.JS), and set dog to undefined.
However, if you call it as a constructor, as var dog = new Dog(), it will make a new object, and set its constructor to this function, and assign this new object to dog. It will set its internal prototype (which can be accessed in some browsers as dog.__proto__) to the constructor's prototype (Dog.prototype). Or, in pseudocode,
var dog = {
legs: 4
};
dog.constructor = Dog;
dog.__proto__ = Dog.prototype; // same as dog.constructor.prototype
Thus, dog.constructor.prototype is not, strictly speaking, the prototype of dog, it is the object that will get assigned to the prototype when the constructor function is run. And in particular, Dog.prototype is not prototype of the Dog function (just the prototype that its instances will acquire). The reason prototype is not available on non-functions is because non-functions can't be used as constructors, so it makes no sense to have it (since its only function is to be copied to constructed instance objects' __proto__).
The object in your example still has a prototype, but not directly accessible; you can either go the hacky route in the browsers that allow it (a.__proto__), or ask the browser nicely (Object.getPrototypeOf(a)).
You can use Object.getPrototypeOf() instead to return you the prototype of Object.
To see this in your browser devtools, run the following:
var a = {flag: 1};
console.dir(Object.getPrototypeOf(a));
In the past when creating "classes" in JavaScript, I have done it like this:
function Dog(name){
this.name=name;
this.sound = function(){
return "Wuf";
};
}
However, I just saw someone do it like this instead:
var Dog = (function () {
function Dog(name) {
this.name = name;
}
Dog.prototype.sound = function () {
return "Wuf";
};
return Dog;
})();
Can you do it both ways, or is the way I've done it wrong? In that case, why? And what exactly is the difference between the two in terms of what we end up with? In both cases we can create an object by saying:
var fido = new Dog("Fido");
fido.sound();
I hope someone will enlighten me.
There are two important differences between your way and theirs.
Wrapping in a self invoking function ((function() { ... })();)
Using the .prototype property over this. for methods.
Wrapping things in a self invoking function, then assigning the result (as defined in the return statement to a variable is called the module pattern. It's a common pattern to ensure scope is more controlled.
Using Dog.prototype.sound = function() {} is preferable to this.sound = function(). The difference is that Dog.prototype.sound is defined once for all objects with the Dog constructor, and the this.sound = function() {} is defined again for each Dog object created.
The rule of thumb is: Things that are individual to an object (usually its properties) are to be defined on this, while things that are shared to all objects of the same type (usually functions) are to be defined on the prototype.
With your code, you're creating a new function sound for every new Dog instance that's being created. Javascript's prototype avoids this by creating only a single function which all object instances share; basically classical inheritance.
In the second code you're showing that's just additionally wrapped in an IIFE, which doesn't do much in this case.
The first is the traditional method of creating a constructor. The second an immediately invoked function expression that returns a constructor. This method allows you to keep variables within the module without leaking out into the global scope which could be an issue.
And what exactly is the difference between the two in terms of what we end up with?
They both, as you've seen, have the same result. The others have talked about prototype so I won't mention it here.
The second is preferable because it takes advantage of Javascript's prototypal inheritance mechanism.
Prototypes
Javascript inheritance is a cause of confusion, but it's actually fairly simple: every object has a prototype, which is an object that we will check when we try to access a property not on the original object. The prototype will, itself, have a prototype; in a simple case, like Dog, this will probably be Object.prototype.
In both of your examples, because of how the new operator works, we will end up with a prototype chain that looks like this: fido->Dog.prototype->Object.prototype. So, if we try to look for the name property on Fido, we'll find it right there on the object. If, on the other hand, we look for the hasOwnProperty property, we'll fail to find it on Fido, fail to find it on Dog.prototype, and then reach Object.prototype, where we'll find it.
In the case of sound, your examples define it in two different places: in the first case, fido and every other dog we create will have their own copy of the function. In the second case, Dog.prototype will have a single copy of the function, which will be accessed by individual dogs when the method is called. This avoids wasting resources on storing duplicates of the sound function.
It also means that we can extend the prototype chain; maybe we want a Corgi class that inherits the sound function from Dog. In the second case, we can simply ensure that Dog.prototype is in Corgi.prototype's prototype chain; in the first, we would need to create an actual Dog and put it in the prototype chain.