Can't inherit constructor from parent class - javascript

I have problem with inheritance of consturctor:
function Alive(name) {
this.name = name;
}
var Cat = new Function();
Cat.prototype = new Alive();
Cat.prototype.constructor = Alive;
var cat = new Cat('Thomas');
alert(cat.name);
alert show undefined. What i do wrong? jsfiddle

Looks like you want the parent constructor to get called automatically, that's not supported without some extra work. Your code should look like the following
function Alive(name) {
this.name = name;
}
function Cat(name) {
// Call the parent constructor
Alive.call(this, name);
}
Cat.prototype = new Alive();
// This line is to fix the constructor which was
// erroneously set to Alive in the line above
Cat.prototype.constructor = Cat;
var cat = new Cat('Thomas');
alert(cat.name);
If you use a library to implement inheritance, you don't have to worry about this. They can even call your parent constructor automatically if you don't want to create an empty constructor. The above code is still not ideal. See a post I wrote that talks about the 'right' way to do inheritance. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

Because Cat doesn't accept an argument. Here's what you want:
function Alive(name) {
this.name = name;
}
function Cat(name) {
Alive.call(this, name);
}
// since there's nothing on the prototype, this isn't necessary.
// Cat.prototype = new Alive();
var cat = new Cat('Tomas');
alert(cat.name);

Related

javascript proto-chaining confusion on this

While going over below tutorial code
Animal = function(name) {this.name = name}
Animal.prototype.eats = function(){
return this.name + ' is eating'
}
Chordate = function(name){Animal.call(this,name)}
I understand how call works (basically, in this case, this becomes this)... but my question is, how does one use this?
I am sorry, I understand how prototype works.. But really, I don't understand once you setup Chordate as above.. how does one use it?
How is this useful? or How are you now suppose to specify the this?
Can someone please explain w/ example?
Create a link to Animal's prototype methods:
Chordate.prototype = Object.create(Animal.prototype)
Then new it up:
var c = new Chordate('my name');
c.eats();
The line Animal.call(this,name) is like making a call to a base constructor. It executes the Animal constructor function and passes in name, but uses the correct this context:
Animal = function(name) {
// "this" will be your Chordate instance
this.name = name
}
Lets imagine youre constructing an Animal:
new Animal();
and during construction it draws a new animal onto the canvas. The constructor would look like this:
function Animal(){
canvas.draw(this.x,this.y,this.image);
}
Now youve got a tiger. The tiger should roar if it is constructed.
function Tiger(){
this.roar();
}
And now? Its an animal so its added to the canvas right? No. Because of js inheritance system, you need to do this manually. So when the tiger gets constructed, you also need to construct it as an animal:
Animal.call(this);
This is even easier with the new class syntax:
class Animal{
constructor(){
this.draw(this.x,this.y,this.image);
}
}
class Tiger extends Animal{
constructor(){
this.roar();
super()//construct Animal
}
}
This is just meant to be an addition to the other answers, and would be too long for a comment.
Perhaps it helps you to understand what the new operator actually does:
var newInstance = new ConstructorFunction(arg1, arg2);
Create a new object. The prototype of this object is ConstructorFunction.prototype:
var newInstance = Object.create(ConstructorFunction.prototype);
Call the ConstructorFunction with the newly created object:
ConstructorFunction.call(newInstance, arg1, arg2);
If ConstructorFunction inherits from another "class", it has to call its super constructor. That's what the following code does:
function Parent () {
// this === newInstance
}
function Child () {
// this === newInstance
Parent.call(this); // call the super constructor
}
Child.prototype = Object.create(Parent.prototype);
var newInstance = new Child();
// or:
var newInstance = Object.create(Child.prototype);
Child.call(newInstance); // call the constructor, which calls the super constructor

How to set the constructor of an Object without changing to a new Object?

In this related question, the answer for setting a constructor is like so:
function OldClass() {
alert("old class with incomplete constructor")
}
function ChangedClass(){
alert('new class with same prototype and more complete constructor');
}
ChangedClass.prototype = OldClass.prototype;
var theClassIWant = new ChangedClass();
This is not really setting the constructor, it's making a new object and inheriting the prototype. How can I set the constructor of an Object without changing to a new Object? Is it possible?
P.S. I want something like this:
//non working code
var Foo = function() {}
Foo.prototype.constructor = function(bar_val) {
this.bar = bar_val;
}
var fez = new Foo("cat")
console.log(fez.bar); // outputs: cat;
constructor is a property of the constructor function's prototype, which points to the function itself by default.
When you modify Foo.prototype.constructor, this property points to another function. However, the constructor function Foo remains. So when you create an object, you are still instantiate the constructor function Foo, not the one Foo.prototype.constructor points to.
This is why your code doesn't work. Then let's talk why we need to change the constructor and how to.
In ES5 and before, we take advantage of prototype to simulate a class inheritance mechanism. Which looks like this:
// parent class
function Person(name) {
this.name = name
}
// define parent method
Person.prototype.say = function() {
console.log(this.name)
}
// child class
function Coder(name, major) {
Person.call(this, name) // inherits parent properties
this.job = 'Coding'
this.major = major
}
// inherits properties and methods from parent prototype
Coder.prototype = new Person()
// define child method
Coder.prototype.work = function() {
console.log('I write ' + this.major)
}
// instantiate a child object
var me = new Coder('Leo', 'JavaScript')
console.log(me) // {name: "Leo", job: "Coding", major: "JavaScript"}
Everything looks perfect, but there a problem:
console.log(me.constructor) // Person
What? Isn't me constructed with Coder? Why?
Go back to the first line of this answer, read it again: constructor is a property of the constructor function's prototype.
Originally Coder.prototype.constructor is Coder itself. But with this line: Coder.prototype = new Person(), it got changed. Coder.prototype.constructor now equals Person.prototype.constructor, which is Person.
Well, some would say, try instanceof. Yes, that works:
me instanceof Coder // true
But it's also true for Person, because Coder is a sub class of it:
me instanceof Person // true
This doesn't make sense so we need to fix the constructor problem. That's why we use Coder.prototype.constructor = Coder after Coder.prototype = new Person(), to get back the original constructor.
Full code looks like this:
// parent class
function Person(name) {
this.name = name
}
Person.prototype.say = function() {
console.log(this.name)
}
// child class
function Coder(name, major) {
Person.call(this, name) // inherits parent class
this.job = 'Coding'
this.major = major
}
Coder.prototype = new Person() // inherits parent's prototype
Coder.prototype.constructor = Coder // get back constructor
Coder.prototype.work = function() {
console.log('I write ' + this.major)
}
myClass = {
constructor: function(text){
console.log(text);
}
}
let ob = Object.create(myClass);
ob.constructor("old constructor "); //Output: old constructor
myClass.constructor = function(){
console.log("new constructor ")
}
ob.constructor(); //Output: new constructor
You can do this with every property or function of a class.
Watch this Video here. It explains it perfectly.

Get name of derived constructor in Javascript

Is it possible to get the name of the derived "class" in the following example? I'd like to somehow have the output be "ChildClass", but instead it's "ParentClass".
function ParentClass() { this.name = 'Bob' }
function ChildClass() { this.name = 'Fred' }
ChildClass.prototype = Object.create(ParentClass.prototype);
var child_instance = new ChildClass()
console.log('ChildClass type:', child_instance.constructor.name)
I realize I can do this.my_type = 'ChildClass' in the ChildClass constructor, but I have many classes that extend ParentClass and doing this everywhere would be inconvenient.
The problem in your case is that you're overwriting the prototype property of ChildClass but you're not reseting the constructor property on the new prototype. You need to add one extra line:
function ParentClass() {
this.name = "Bob";
}
function ChildClass() {
this.name = "Fred";
}
ChildClass.prototype = Object.create(ParentClass.prototype);
ChildClass.prototype.constructor = ChildClass; // add this line to your code
Now your code will work as expected. The following answer explains why your original code didn't work: https://stackoverflow.com/a/8096017/783743
Personally I don't like writing "classes" like this with the constructor and the prototype dangling separately. It's just too tedious to type, incoherent, a pain on the eyes and difficult to maintain. Hence I use the following utility function to create classes:
function defclass(base, body) {
var uber = base.prototype;
var prototype = Object.create(uber);
var constructor = (body.call(prototype, uber), prototype.constructor);
constructor.prototype = prototype;
return constructor;
}
Now you can create classes as follows:
var ParentClass = defclass(Object, function () {
this.constructor = function () {
this.name = "Bob";
};
});
var ChildClass = defclass(ParentClass, function () {
this.constructor = function () {
this.name = "Fred";
};
});
This method has several advantages:
Inheritance and class definition have been combined into one.
The constructor is just another prototype method.
Everything is nicely encapsulated within a single closure.
Calling base class prototype methods is easy.
You can create private static functions easily.
Hope that helps.

How to implement super mechanism in javascript through prototype?

I am struggling to understand the constructor invocation pattern in Javascript.
I have a base object Mammal ( would it be incorrect to use the term class ? ) and an inherited object Cat. In the following code the object Cat correctly inherits from the Mammal object.
/*
Mammal base Object
*/
var Mammal = function(name) {
this.name = name;
}
Mammal.prototype.get_name = function() {
return this.name;
}
Mammal.prototype.says = function () {
return this.saying || '';
}
/*
Cat object
*/
var Cat = function (name) {
this.saying = "Meow";
this.name = name;
}
Cat.prototype.purr = function (number) {
var i =0, s='';
for ( i=0; i<number; i++)
if (s)
s +='-';
s+='r';
return s;
}
Cat.prototype = new Mammal();
console.log("Pseudo classical inheritance approach");
var mammal = new Mammal(" I am a mammal");
console.log("Who are you ? " + mammal.get_name());
console.log("What are you saying? " + mammal.says());
var cat = new Cat('I am a cat');
console.log("Who are you ? " + cat.get_name());
console.log("What are you saying? " + cat.says());
What I don't like in this pattern is how the constructor of the base object is used. The object Cat does not reuse correctly the constructor of the base class Mammal. I would like to have a more flexibility. Each time a Cat object is created, the constructor of the Mammal object is invoked with no arguments. I would like to use a mechanism similar to the "super" keyword in Java, so that when the constructor of Cat is called with name as parameter, also the constructor of Mammal is called with name as parameter.
I tried to implement the Cat constructor as follows :
var Cat = function (name) {
this.saying = "Meow";
// Super (name);
this.prototype = new Mammal(name);
}
This does not work as expected. this.prototype is undefined. why? Why this approach is completely wrong? does this point to the newly Cat object?
I know, there are different ways to implement inheritance in javaScript, but I am wondering if there is a way to implement the super mechanism like in Java.
Thanks. :D
How about
var Cat = function (name) {
this.saying = "Meow";
// Super (name);
Mammal.call( this, name );
}
Yes, I'm afraid that's not how you set up hierarchies. It's close, but there are a couple of key issues. (One of which — calling new Mammal() to create Cat.prototype — is a very, very, very frequent error you see in a lot of blog posts and such.)
Here's a simple example of doing it correctly:
// A function to set up the link between a child and parent
function derive(Child, Parent) {
// `ctor` is a temporary function we use so we can get an object
// backed by `Parent.prototype` but without calling `Parent`.
    function ctor() { }
// Borrow the prototype
    ctor.prototype = Parent.prototype;
// Create an object backed by `Parent.prototype` and use it as
// `Child`'s prototype
    Child.prototype = new ctor();
// Some housekeeping to make the prototype look like the ones
// the JavaScript engine creates normally.
    Child.prototype.constructor = Child;
// Note: If we can rely on ES5 features, we could use
// `Object.create` instead of the `ctor` function.
}
// The parent constructor
var Mammal = function(name) {
this.name = name;
};
// Some stuff for its prototype
Mammal.prototype.get_name = function() {
return this.name;
};
Mammal.prototype.says = function () {
return this.saying || '';
};
// The child constructor
var Cat = function(name) {
Mammal.call(this, name);
this.saying = "Meow";
};
// Hook it up to the parent
derive(Cat, Mammal);
// Add some things to its prototype
Cat.prototype.purr = function (number) {
var i =0, s='';
for ( i=0; i<number; i++)
if (s)
s +='-';
s+='r';
return s;
};
If you're interested in doing inheritance hierarchies in JavaScript, you may find my Lineage script useful. You may or may not choose to use it, but it demonstrates how to set things up, a way to do calls to the parent's version of methods ("supercalls"), etc. In particular, this documentation page comparing using Lineage to not using it shows how to do this without any helper script. But there's a reason I wrote a helper script to do it. :-)
this.prototype is undefined, because no one defined it.
Cat is a function. As such, it has a property prototype. That's mandated by the ECMAScript standard.
this is an object that is not a function. As such, the ECMAScript standard does not mandate that it has a prototype property.
If this is a Cat (i.e. an object that was or is created using new Cat), then it has, for the sake of specification, an internal [[Prototype]] property which is a Mamal. But this mamal is not accessible directly (as implied by the word internal). When you say var maru = new Cat(), then maru.[[Prototype]] is linked to Cat.prototype. That's how maru knows about future methods of mamals.

Prototypal inheritance in JS and how to get parent properties

I'm trying to have properties inherit from a parent, but I'm not clear as to the right way of doing it.
Lets say I have:
var Animal = function(name){
this.offspring = [];
this.name = name;
return this;
}
Animal.prototype.createOffspring = function(name){
name = name || 'Baby '+(this.offspring.length+1);
this.offspring.push(name);
return this;
}
Now I want to add a sub prototype inherit so I don't have to manually add everything from the parent. For example, lets say I want to add a Cat based from Animal
I'd like to do this, like if it were an Animal
var pet = new Cat('Kitty');
pet.createOffspring();
Without manually having to add name and createOffspring to the Cat constructor which is really just an Animal, but with some other added functionality (like .meow() or something).
// Parent
function Animal() {
this.name = 'An animal';
}
// Some child
function Cat() {
this.speaks = 'Meow';
}
// Here comes inheritence
Cat.prototype = new Animal();
// Or like that
// but don't forget to put all inheritable fields to Animal's prototype
Cat.prototype = Object.create(Animal.prototype);
// Let 'instanceof' work. Don't forget the following line,
// because we eraese the info about constructor of Cat instances.
Cat.prototype.constructor = Cat;
// Add some custom method
Cat.prototype.meow = function() { return this.speaks; }
var cat = new Cat();
var animal = new Animal();
/// Some tests
cat.name; // A animal
animal.name; // An animal
cat.meow(); // Meow!
cat instanceof Cat; // true
cat instanceof Animal; // true
That's it?
(UPD: Error with prototype fixed)
(UPD2: Sorry. It is late night, I make a lot of mistakes.. I must go sleep)
There is also another solution, but its Chrome,FF-specific (maybe others):
// Animal and Cat functions from above, but
Cat.prototype = {
__proto__: Animal.prototype,
constructor: Cat,
meow: function() { ... }
}
Looks shorter, but not'd be tempted by this: it's better to follow ECMAScript standart.
There are a number of different patterns for implementing inheritance like you're describing in JavaScript, and they have subtle differences as far as how they treat the prototype objects.
Here's are a couple of good references on the prototype pattern and the constructor pattern to get you started.
And here's a simple implementation of what you described.

Categories