how to implement javascript inheritance - javascript

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);
}
}

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"

Chaining prototypes doesn't work

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();

Altering [object].prototype vs. [object]'s nested functions

This tutorial on prototypical inheritance uses the following code as an example of a Constructable object:
var Person = function (name) {
this.name = name;
};
var tom = new Person('tom');
But then goes on to say that if they want to change the Person object that tom was constructed with, then it should be done by altering Person.prototype:
Person.prototype.say = function (words) {
alert(this.name + ' says "' + words + '"');
};
But why does the prototype (which is Person) have to be altered? Why not just change Person directly like so:
Person.say = function (words) {
alert(this.name + ' says "' + words + '"');
};
Is there a difference?
There is an important distinction to make between the function, and the object returned when treating the function as a constructor.
Person.say = function()
Isn't actually assigning a property to the function, which is it's own object, this has no effect on the generated objects, which inherit the prototype of the Person, overwritten with any changes made within the constructor call itself(hence why this.name still works).
var Person = function (name) {
this.name = name;
};
var tom = new Person('tom');
console.log(tom.__proto__);
// Object {}
Person.prototype.say = function (words) {
alert(this.name + ' says "' + words + '"');
};
console.log(tom.__proto__);
// Object {say: function}
When you call a method on tom if tom doesn't have the method it will look at the prototype, see if that has the method, you're not adding the method to tom ever, only the prototype it inherits from.
The following code binds the say function to the object prototype. When you create a Person instance, the function is called against the data in this instance.
Person.prototype.say = function (words) {
alert(this.name + ' says "' + words + '"');
};
The following code binds the say function to the object in a static fashion (thus, not available per-instance)
Person.say = function (words) {
alert(this.name + ' says "' + words + '"');
};
The following alternative is this, which is a per-instance function, but is not bound to the prototype, rather the say function is created per instance, in the same way that name is created.
Just FYI, this method is NOT recommended (I'm just adding this for completeness) - It is recommended to bind your instance functions to the prototype:
var Person = function(name) {
this.name = name;
this.say = function(words) {
alert(this.name + " says " + words);
};
};
Prototype vs Per-instance:
Binding functions to the prototype (Person.prototype.say = function...) consumes less memory as one function is shared across all instances of the object.
Binding functions per-instance (this.say = function...) consumes more memory because a function is created for every instance created (nothing is shared), though this has the advantage of being able to access private members, which is not possible with prototype bound functions.
Overview:
Static binding: Person.say = function() { ... }
Prototype binding: Person.prototype.say - function() { ... }
Instance binding: function Person() { this.say = function() { ... } ... }
The difference is in memory occupation.
In your case using or not prototype does not change because you have only one istance of Person.
But if you create a lot of istance every istance will have own say function, instead with prototype the function will be shared.

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.

JavaScript Puzzle I can't figure out

This is a kata for code wars, and I can't seem to figure it out. I have never worked with JavaScript before.
I know the answer is probably simple, but I just can't seem to figure out what they are looking for even after many hours of searching. I know that name in the greet function is not defined, but when I define it, it says it's not the value it's looking for.
function Person(name){
this.name = name;
}
Person.prototype.greet = function(otherName){
return "Hi " + otherName + ", my name is " + name;
}
Please help and an explanation would be greatly appreciated.
Don't really understand what you are looking for but hope this will shed some light : (try on your console)
function Person(name){
this.name = name;
}
Person.prototype.greet = function(otherName){
return "Hi " + otherName + ", my name is " + this.name;
}
var p = new Person('jack');
p.greet('sparrow');
Tyagi gave you an explanation of how to call it but did not show what the actual problem with the code is:
Here's my (very similar) example:
function Person(name) {
this.name = name;
}
Person.prototype.greet = function (otherName) {
return "Hi " + otherName + ", my name is " + this.name;
}
var john = new Person("John");
$("#result").text(john.greet("Mike"));
and if you click through to this JSFiddle then you can see it actually working. The difference between the two is simply the change of "name" to "this.name" in the greet() function. You're attaching a new function to every Person object but it doesn't automatically look for the name variable on the object within that function the way it's defined.
I don't get your question but i will try to explain how it works:
// define a function (or class) called 'Person'
function Person(name){
// add data members 'name' to 'this' pointer which points to current context
this.name = name;
}
// define a method in 'Person' class
Person.prototype.greet = function(otherName){
//'othername' is an argument which you passed while calling 'greet' method
//'name' is an data memeber which you declared while creating 'Person' class
// will return value when you call this method
return "Hi " + otherName + ", my name is " + this.name;
}
// create a class object
var person = new Person('Mohit');
// call its 'greet' method
// will show an alert 'Hi Bekk, my name is Mohit'
alert(person.greet('Bekk'));
JSFiddle Link: http://jsfiddle.net/QqnL5/

Categories