By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,053 Members | 939 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,053 IT Pros & Developers. It's quick & easy.

Constructor is never called

P: n/a
Jun
I have following script

<script>
var Animal = function(name){
this.name = name;
}
Animal.prototype.eat = function (food)
{
alert(this.name + " eat " + food);
}

//constructor for Dog
var Dog = function(){
}

//"inheriting" from Animal
Dog.prototype = new Animal();
Dog.prototype.constructor = Animal;

var myDog = new Dog("ddd");

myDog.eat("bone");

</script>

The result was that Dog's constructor was called but Animal's constructor
was never called so I got "undefined eat bone".

Is the javascript inheritant doesn't support calling super constructor or
I didn't use "Dog.prototype.constructor" correctly?

thanks
Jul 20 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a

"Jun" <ju*********@hotmail.com> schreef in bericht
news:de**************************@posting.google.c om...

The result was that Dog's constructor was called but Animal's constructor
was never called so I got "undefined eat bone".

Is the javascript inheritant doesn't support calling super constructor or
I didn't use "Dog.prototype.constructor" correctly?


Actually, it is called. But since you are not passing it an argument and the
Dog constructor doesn't set the name property, it remains undefined.

To fix this, you could either pass the argument to the Dog constructor:

//constructor for Dog
var Dog = function(name) {
this.name = name;
}

or pass it when initiating the prototype property:
Dog.prototype = new Animal("ddd");

Anither option is to define a setter method in the Animal constructor
function:

var Animal = function() {
this.setName = function (name) {
this.name = name;
};
}

This can then be called seperatly to set the dog's name:
.....
var myDog = new Dog();
myDog.setName("goofy");

myDog.eat("bone");
.....

JW

Jul 20 '05 #2

P: n/a
ju*********@hotmail.com (Jun) writes:
<script>
For pedantic reasons, I'll remind you (and everybody else :) that the
type attribute is required in HTML 4 and later.

<script type="text/javascript">
var Animal = function(name){
this.name = name;
} Animal.prototype.eat = function (food)
{
alert(this.name + " eat " + food);
}

//constructor for Dog
var Dog = function(){
As Janwillem Borleffs said, you don't set the name.
Javascript doesn't call the superclass' constructor, mostly because
there are no classes in Javascript at all, so no superclasses either.
If you want to call the superclass' constructor, you have to do
it manually:
Animal.call(this,arguments[0]);
or just (since you set it up with "Dog.prototype.constructor = Animal;")
this.constructor(arguments[0]);
(you might want to make Dog take an argument :)
}

//"inheriting" from Animal
Don't say "inheriting". It isn't. Javascript is prototype based, not
class based, so there is no real inheriting.
Dog.prototype = new Animal();
This means that a new Dog object will have a [[prototype]] reference
to an Animal object with an undefined name (you call Animal with
no argument, so the name gets set to undefined)>
Dog.prototype.constructor = Animal;
The prototype's constructor is never called automatically. If you
want to call it, you must do it yourself.
The result was that Dog's constructor was called but Animal's constructor
was never called so I got "undefined eat bone".
You called it yourself in
"dog.prototype = new Animal();"
It is never called automatically.
Is the javascript inheritant doesn't support calling super constructor or
I didn't use "Dog.prototype.constructor" correctly?


There is no inheritance. You didn't say what you expected
Dog.prototype.constructor to do, but it probably doesn't do what you
expect. (When asking for help, always say both what actually happenes
and what you expected to happen).

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #3

P: n/a
Fox


Jun wrote:

I have following script

<script>
var Animal = function(name){
this.name = name;
}

Animal.prototype.eat = function (food)
{
alert(this.name + " eat " + food);
}
If you *know* you're going to include this method -- just declare it
within the object definition:

function
Animal(name)
{
this.name = name;

this.eat = function(food)
{
alert(this.name + " eats " + food);
}
}
Use prototype for predefined objects like Array, Number, String, etc...
or declaring superclasses...

//constructor for Dog
var Dog = function(){
}
This is not an object (much less a constructor) -- it's an empty
function... in order to be considered an object, it *requires* at least
one property or method utilizing the keyword "this".
//"inheriting" from Animal
Dog.prototype = new Animal();
Dog.prototype.constructor = Animal;
Not required and not recommended -- the constructor is automatically
Animal (or whatever topmost level object is utilized).

var myDog = new Dog("ddd");

myDog.eat("bone");

</script>

The result was that Dog's constructor was called but Animal's constructor
was never called so I got "undefined eat bone".

Is the javascript inheritant doesn't support calling super constructor or
I didn't use "Dog.prototype.constructor" correctly?
answered...

thanks


The "super" constructor IS automatically called as soon as it is
prototyped from the "subclass" [or, probably, more technically, as soon
as the object prototyped is parsed since you can prototype the
superclass prior to defining it] -- it becomes, essentially, the *only*
constructor used for the object.

Dog's constructor (if Dog is actually an Object) is not Dog, it's
Animal, as you will see from the alerts:
function
Animal(args)
{
this.genus = args;

alert("constructor called -- animal genus = " + this.genus);
// fires when called...

// use a JS superclass as repository
// for common properties or methods

this.getType = function()
{
alert (this.type); // declared in Dog
}
this.getBreed = function()
{
alert (this.breed); // declared in Cat
}

}

function
Dog(arg)
{
alert(this.constructor); // shows function Animal
this.type = arg;

}

function
Cat(arg)
{
alert(this.constructor); // shows function Animal
this.breed = arg; // different than Dog...
}

// the point of subclassing is to have different sets of properties and methods
// particular to that class -- the super providing all of the common properties
// and methods...

Dog.prototype = new Animal("canis"); // args common to ALL Dog objects
Cat.prototype = new Animal("felis"); // args common to ALL Cat objects

// note -- do not use Cat/Dog.prototype.constructor
// the constructor is automatically set by JS and
// in this case, the constructor => "Animal" [the entire function
declaration]
// It is at this point that the "superclass" constructor is "fired"
// you get the "constructor called..." alert -- 2 in a row
var d = new Dog("doberman");
var c = new Cat("siamese");

// these fire the constructor Animal alerts and set their respective
"local" properties
// as per the instructions within these object declarations
// use subclass reference to access superclass/inherited methods/properties:
d.getType();
d.getBreed(); // shows "undefined"
c.getType(); // shows undefined
c.getBreed();

alert(d.genus + "\n" + c.genus); // shows "superclass" property of instance

Taking this even further, you have the case of extending the subclass
with yet another subclass:

function
dogFood(brand)
{
alert(this.constructor); // again -- will show Animal!
this.brand = brand;
}

dogFood.prototype = new Dog("all breeds"); // notice -- NOT Animal here
Even though Dog is used as the prototype declaration, you will see that
Animal is actually the constructor called [since it is the constructor
for Dog and Cat] -- "all breeds" is loaded into the Dog instance's type
property as default and:

var df = new dogFood("purina");

will load "purina" into the brand property.

df.genus will show "canis" and calling df.getType() will fire the alert
showing "all breeds" as the type.
Now, for fun, put:

function
Lifeform(kind)
{

this.lifeform = kind;

this.showAll = function()
{
var s = "";
for(var i in this)
{
s += i + ": " + this[i] + "\n";
}

alert(s);
}
}

Animal.prototype = Lifeform("fur-bearin' critter");
// can be declared BEFORE Animal is actually declared

at the head of everything above...

and

d.showAll(); // called from Dog instance
and
df.showAll(); // called from dogFood instance

to observe the differences between object instances... what you end up
with is a large object with everything included -- essentially something like:

var dog = new (Dog + Animal + Lifeform); // very pseudocode...
// no such thing in JS
var cat = new (Cat + Animal + Lifeform);

var dogfood = new (dogFood + Dog + Animal + Lifeform);
You can change the "default" values passed to "superclasses" anytime you
wish by redeclaring the prototype:

dogFood.prototype = new Dog("my pet"); // changed from "all breeds"
var dogfood2 = new dogFood("iams");

Now compare df.showAll() and dogfood2.showAll() -- you'll see that
df.type still shows "all breeds" and "purina" while dogfood2.type
(default) has changed to "my pet" and brand to "iams". The new
prototype takes effect for all subsequent instantiations of class
dogFood (until explicitly changed). In other words, changing the
prototype does not change already existant instances of the object...
[you are not limited to redeclaring the prototype of the extended class
-- you could as easily redefine prototype new Animal("new default") or
Lifeform (etc) from any point in the "chain" of inheriting objects. This
gives JS a level of flexibility beyond that available from more
conventional class oriented objects where these kinds of "on-the-fly"
changes are not available.

Nowhere did I use .call() -- nowhere did I use .constructor... Objects
in JS are not that complicated. Logic dictates that there is inheritance
since methods and/or properties do not need to be redeclared in each
"class" declaration or overridden (although that is your option if you
so choose.) Although JS has a different object model than other
programming languages like Java, the *language* that we have to describe
object models in general is limited to a similar set of terms that are
used to describe both prototype based objects as well as class based
objects...so, superclass/subclass and inheritance are used to describe
similar *functionalities* in both even though there are syntactical
differences [there is, technically, no class declarator in JS; however,
there is likewise no terminology for superobject/subobject, super/sub
prototype, or super/sub function either]. Check out Netscape's
JavaScript User's Guide for an excellent description (and examples) of
the differences between prototype-based and class-based object oriented languages.
Hope this helps...
Jul 20 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.