Chaining prototypes doesn't work - javascript

I wonder why based on my code, cat.getIt(); won't work. I created two objects and wanted the "cat" object to have the "dog" object as its prototype. It worked but what doesn't work is the dogs method "getIt" won't get inherited by the object cat even though I said: Cat.prototype=new Dog() (Cat.prototype=Object.create(Dog.prototype); didn't work too). Does anyone know why?
function Dog (name){
this.name=name;
this.age=[];
}
var myDog= new Dog("Jo");
Dog.prototype.sayHi=function(){
return "My name is " + this.name + ", I'm a Dog";
};
Dog.prototype.getIt = function(){
var small = {
name: "Baby " + this.name
};
this.age = [small];
return small;
}
myDog.getIt();
function Cat(name,color){
Dog.call(this,name);
this.color=color;
}
var cat = new Cat("Lexy", "red");
//Cat.prototype=Object.create(Dog.prototype); //Or should I do it like that?
Cat.prototype=new Dog();
cat.getIt();

Related

The ratio of a .__ proto __ and b() [duplicate]

I am new at learning JavaScript concepts. Want to understand how prototypical inheritance work. My impression was if your class inherits its parent, and you have a same named method in prototypes of both classes, when you call the method on child instance, the method in the child prototype will be called.
Code:
function Animal(name) {
this.name = name;
}
Animal.prototype.printName = function () {
console.log(this.name + ' in animal prototype');
}
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype.printName = function () {
console.log(this.name + ' in cat prototype');
}
Cat.prototype = Object.create(Animal.prototype);
var anm1 = new Animal('mr cupcake');
anm1.printName();
var cat1 = new Cat('cat');
cat1.printName();
On calling cat1.printName() I expected it to log 'cat in cat prototype' but it logged 'cat in Animal prototype'. Could someone please explain the reason to me. Thanks.
You are correct, but your override of the printName() function is, itself, being overridden by the next line when you reset the Cat.prototype. Simply moving the order of the code fixes the issue:
function Animal(name) {
this.name = name;
}
Animal.prototype.printName = function() {
console.log(this.name + ' in animal prototype');
}
function Cat(name) {
Animal.call(this, name);
}
// OLD LOCATION of code
// This was overriding your override!
// Setting the prototype of an object to another object
// is the basis for JavaScript's prototypical inhertiance
// This line replaces the existing prototype object (which is
// where your override was) with a completely new object.
Cat.prototype = Object.create(Animal.prototype);
// NEW LOCATION
// AFTER setting the prototype (and creating inheritance),
// it is safe to do the override:
Cat.prototype.printName = function() {
console.log(this.name + ' in cat prototype');
}
var anm1 = new Animal('mr cupcake');
anm1.printName(); // "mr cupcake in animal prototype"
var cat1 = new Cat('cat');
cat1.printName(); // "cat in cat prototype"

ES6 Classes ability to perform polymorphism

I am trying to emulate polymorphism through ES6 Classes, in order to be able to better understand this theory.
Concept is clear (designing objects to share behaviors and to be able to override shared behaviors with specific ones) but I am afraid my code above is not a valid polymorphism example.
Due to my lack of experience, I appreciate if you answer these questions in a comprehensive way:
The fact that both Classes have an equally named method, and that instances made from each Class get access correctly to their respective methods, makes this a polymorphic example?
In case this does not emulate polimorphism, what changes should be
done in the code for it?
I've tried removing the Employee.prototype = new Person(); line, and it still works. This is why I am afraid I'm not getting this concept.
class Person {
constructor (name, age) {
this._name = name;
this._age = age;
}
}
Person.prototype.showInfo = function(){
return "Im " + this._name + ", aged " + this._age;
};
class Employee {
constructor (name, age, sex) {
this._name = name;
this._age = age;
this._sex = sex;
}
}
Employee.prototype = new Person();
Employee.prototype.showInfo = function(){
return "Im " + this._sex + ", named " + this._name + ", aged " + this._age;
};
var myPerson = new Person('Jon', 20);
var myEmployee = new Employee('Doe', 10, 'men');
document.write(myPerson.showInfo() + "<br><br>"); // Im Jon, aged 20
document.write(myEmployee.showInfo() + "<br><br>"); // Im men, named Doe, aged 10
Every JavaScript object has an internal "prototype" property, often called [[prototype]], which points to the object from which it directly inherits.
Every JavaScript function [object] has a property prototype, which is initialized with an [nearly] empty object. When you create a new instance of this function by calling it as a constructor, the [[prototype]] of that new object will point to the constructor's prototype object.
So, when you write this var myPerson = new Person('Jon', 20);,you have the method showInfo because you have this
Person.prototype.showInfo = function(){
return "Im " + this._name + ", aged " + this._age;
};
With ES6 if you want to see the polymorphism you could do that :
class Person {
constructor (name, age) {
this._name = name;
this._age = age;
}
showInfo () {
return "Im " + this._name + ", aged " + this._age;
}
}
class Employee extends Person {
constructor (name, age, sex) {
super(name,age);
this._sex = sex;
}
showInfo(){
return "Im " + this._sex + ", named " + this._name + ", aged " + this._age;
}
}
var myPerson = new Person('Jon', 20);
var myEmployee = new Employee('Doe', 10, 'men');
document.write(myPerson.showInfo() + "<br><br>"); // Im Jon, aged 20
document.write(myEmployee.showInfo() + "<br><br>"); // Im men, named Doe, aged 10
You are mixing ES5 and ES6. Also, you simply created two classes. Employee does not really inherit from Person. The code you want should look like this:
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
showInfo() {
return `I'm ${this._name}, aged ${this._age}.`;
}
}
class Employee extends Person {
constructor(name, age, sex) {
super(name, age);
this._sex = sex;
}
showInfo() {
return `I'm a ${this._sex} named ${this._name}, aged ${this._age}.`;
}
}
const alice = new Person("Alice", 20);
const bob = new Employee("Bob", 25, "male");
console.log(alice.showInfo());
console.log(bob.showInfo());
So, here's a quick recap of what's changed.
First off, no need to assign a prototype anymore. Instead, you extend the parent class to create a child class. You can call the parent constructor using the super() call in the child constructor - this will set the properties that are handled by the parent ctor. Note that we don't set name or age in the child ctor anymore! This is why your example still worked after removing the line setting the child prototype: you set the properties manually anyway.
Methods are defined inside the class; no need to use the prototype. You override the method in the child class by just declaring it there.
Should you need any additional clarification, please ask in the comment.

how to implement javascript inheritance

I'm looking into javascript inheritance for the first time, and I don't seem to be able to get it to work, or perhaps I'm not understanding it correctly.
So I have some code here, let's have a look at it:
<script language="javascript" type="text/javascript">
//object and prototype
function cat(name){//object constructor
this.name = name;//property
this.talk = function(){//method
console.log(this.name + " say meeow");
}
}
cat1 = new cat("Cat 1 Felix")
cat1.talk();
cat2 = new cat("cat 2 Joy")
cat2.talk()
//inheritance
function isleManCat(name){
cat.call(this,name)
this.feature = "no tail"
this.detail = function(){
console.log(this.name + " has " + this.feature);
}
}
isleManCat.prototype = new cat();
cat3 = new isleManCat("isle of Man cat")
cat3.talk();
cat3.detail();
</script>
So I have 2 cats objects here and cat1 and cat2 prints the expected results:
Cat 1 Felix say meeow
cat 2 Joy say meeow
. Then cat3 is a isleOfMan() cat which should inherit from cat(), and I would have thought that it would inherit the name property from cat() but it prints undefined:
undefined say meeow
undefined has no tail
Can somebody kindly let me know why it doesn't work and what i'm doing wrong please as I don't seem to understand that?
Thanks
Your third kitten deriving cat won't produce your expected result because the cat constructor won't be called by isleManCat's constructor auto-magically! And your third kitten has no name at all!
// You need to pass the name of the whole cat to this constructor
// to later give it as argument to base constructor (i.e. cat())
function isleManCat(name){
// This is calling cat constructor function setting the "this"
// keyword to the "this" of isleManCat
cat.call(this, name);
this.feature = "no tail"
this.detail = function(){
console.log(this.name + " has " + this.feature);
}
}
In ECMA-Script 5.x you can also use Function.prototype.apply and arguments reserved keyword to pass isleOfMan constructor's arguments as an array to cat:
function isleManCat(){
cat.apply(this, arguments);
this.feature = "no tail"
this.detail = function(){
console.log(this.name + " has " + this.feature);
}
}
And, in ECMA-Script 2015 and above, you can use rest parameters:
function isleManCat(...args){
// This is calling cat constructor function setting the "this"
// keyword to the "this" of isleManCat
cat.apply(this, args);
this.feature = "no tail"
this.detail = function(){
console.log(this.name + " has " + this.feature);
}
}

Javascript: Added function does not appear on parent object

I am trying to understand the prototype inheritance in Javascript. There have been several questions already asked on this, but they do not seem to address the confusion I am having.
How does JavaScript .prototype work?
What is the 'new' keyword in JavaScript?
There are also some great resources on the internet.
http://www.webdeveasy.com/javascript-prototype/
http://javascriptissexy.com/javascript-objects-in-detail/
When I read those resources, I think I understand prototypical inheritance, but when I try some tests in the browser console I realise I am missing something.
Based on the code example below:
(1) why is the added prototype function description() not visible on the parent object animal ?
(2) why is an object created after the description() function is added now missing the original object attributes: name and color?
Example:
Create a simple object.
function animal(){
var name;
var colour;
}
Create two new objects based on the prototype animal
> cat = new animal();
< animal {}
> cat.name = 'cat';
> cat.color = 'black';
> cat
< animal {name: "cat", color: "black"}
Add an attribute to one object only
> dog = new animal();
> dog.name = 'dog';
> dog.color = 'brown';
> dog.bite = 'hurts';
> dog
< animal {name: "dog", color: "brown", bite: "hurts"}
> animal.prototype.description = function(){
console.log('A ' + this.name + ' is ' + this.color); }
< function (){
console.log('A ' + this.name + ' is ' + this.color); }
Add a new function as a prototype. This all works as I expected it to.
> animal
< function animal(){
var name;
var colour;
}
> dog
< animal {name: "dog", color: "brown", bite: "hurts", description: function}
> cat
< animal {name: "cat", color: "black", description: function}
Here is the confusion. the new function description appears on both of the existing dog and cat objects, but it does not appear on the parent object animal
> cat.description;
< function (){
console.log('A ' + this.name + ' is ' + this.color); }
> cat.description();
< A cat is black
A new object cow created from the parent animal now has only the description function, but not the name or color
> cow = new animal();
< animal {description: function}
> cow
< animal {description: function}
EDIT
Based on #Quince's answer, I went back to the browser, but am still confused:
>animal = function(){
this.name;
}
<function (){
this.name;
}
>animal
<function (){
this.name;
}
>cat = new animal();
<animal {}
>cat
<animal {}
In this case the new object cat doesn't seem to inherit the name property from the parent.
in this example here
function animal(){
var name;
var colour;
}
name and colour are private to animal and as such can not be accessed.
now when you run this
cat = new animal();
< animal {}
> cat.name = 'cat';
> cat.color = 'black';
you are actually not setting those private name and colour attributes inside animal you are giving it new attributes called name and colour
when you run the following
animal.prototype.description = function(){
console.log('A ' + this.name + ' is ' + this.color);
}
animal is being given a publicly accessible function called description which is why you can see it when you create a cow, but actually this function will not print anything yet as the animal class does not have a name or color attribute.
options you have here are to change animal to
function animal(){
this.name;
this.colour;
}
although this gives no advantages other letting you know you can set this attributes of the animal, you will still need to set them in order for description to print anything.
Another option if wanting to keep things private and public is to use something along the lines of the revealing module pattern which allows js to keep attributes private to an object by declaring them outside of the object you return.
function Animal() {
//private artibutes
var name;
var colour;
//return publically avaliable functions/attibutes
return {
description: function () {
console.log('A ' + name + ' is ' + colour);
},
setName: function (nameIn) {
name = nameIn;
},
setColour: function (colourIn) {
colour = colourIn;
},
getName: function () {
return name;
},
getColour: function () {
return colour
}
}
};
now the only way to access the private name and color is to use the publicly available functions returned here is a fiddle showing it in action http://jsfiddle.net/leighking2/fxrLpj9v/
Oh and just realized i never actually answered the question in the title, so when you print animal you do not see the added description function as this function is attached to the prototype, animal when printed raw is just a constructor. Anything created using new Animal will inherit from animal's prototype which is why it can be seen in dog and cow

What is the value of this?

I am trying to figure out what 'this' is referencing in my last function (Mamamal.prototype.haveBaby);
var Mammal = function(name){
this.name = name;
this.offspring = [];
};
// var myMammal = new Mammal('Joe');
Mammal.prototype.sayHello = function(){
return 'My name is ' + this.name + ", I'm a Mammal";
};
Mammal.prototype.haveBaby = function(){
debugger;
var childName = "Baby " + this.name;
baby = new this.constructor(childName); //new Cat OR new Mammal
baby.name = childName;
this.offspring.push(baby);
return baby;
};
I am not sure why the syntax
baby - new this.constructor(childName);
is this Mammal.prototype?(then constructor so it would be Mammal.prototype.constructor(childName); That's the only way I know how to set the constructor. Mammal.constructor wouldn't work.
The value of this depends on how a function is called, in your case Mammal.prototype.haveBaby.
If you call it with Mammal.prototype.haveBaby(), then this refers to Mammal.prototype.
If you call it as instance methods (which is more likely), e.g.
var mammal = new Mammal();
var baby = mammal.haveBaby();
then this refers to mammal.
But in both cases you are accessing the same property, since every instance of Mammal inherits the properties of Mammal.protoype. So this.constructor === Mammal.prototype.constructor, no matter in which situation of those two.
Read the MDN documentation for more information about this.

Categories