Constructor is never called

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jun

    Constructor is never called

    I have following script

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


    Animal.prototyp e.eat = function (food)
    {
    alert(this.name + " eat " + food);
    }

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

    //"inheriting " from Animal
    Dog.prototype = new Animal();
    Dog.prototype.c onstructor = 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
  • Janwillem Borleffs

    #2
    Re: Constructor is never called


    "Jun" <junchien888@ho tmail.com> schreef in bericht
    news:de615625.0 311081959.52f22 22b@posting.goo gle.com...[color=blue]
    >
    > 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?
    >[/color]

    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



    Comment

    • Lasse Reichstein Nielsen

      #3
      Re: Constructor is never called

      junchien888@hot mail.com (Jun) writes:
      [color=blue]
      > <script>[/color]

      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">
      [color=blue]
      > var Animal = function(name){
      > this.name = name;
      > }[/color]
      [color=blue]
      > Animal.prototyp e.eat = function (food)
      > {
      > alert(this.name + " eat " + food);
      > }
      >
      > //constructor for Dog
      > var Dog = function(){[/color]

      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(thi s,arguments[0]);
      or just (since you set it up with "Dog.prototype. constructor = Animal;")
      this.constructo r(arguments[0]);
      (you might want to make Dog take an argument :)
      [color=blue]
      > }
      >
      > //"inheriting " from Animal[/color]

      Don't say "inheriting ". It isn't. Javascript is prototype based, not
      class based, so there is no real inheriting.
      [color=blue]
      > Dog.prototype = new Animal();[/color]

      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)>
      [color=blue]
      > Dog.prototype.c onstructor = Animal;[/color]

      The prototype's constructor is never called automatically. If you
      want to call it, you must do it yourself.
      [color=blue]
      > The result was that Dog's constructor was called but Animal's constructor
      > was never called so I got "undefined eat bone".[/color]

      You called it yourself in
      "dog.protot ype = new Animal();"
      It is never called automatically.
      [color=blue]
      > Is the javascript inheritant doesn't support calling super constructor or
      > I didn't use "Dog.prototype. constructor" correctly?[/color]

      There is no inheritance. You didn't say what you expected
      Dog.prototype.c onstructor 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 - lrn@hotpop.com
      DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
      'Faith without judgement merely degrades the spirit divine.'

      Comment

      • Fox

        #4
        Re: Constructor is never called



        Jun wrote:[color=blue]
        >
        > I have following script
        >
        > <script>
        > var Animal = function(name){
        > this.name = name;
        > }
        >
        > Animal.prototyp e.eat = function (food)
        > {
        > alert(this.name + " eat " + food);
        > }[/color]

        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...
        [color=blue]
        >
        > //constructor for Dog
        > var Dog = function(){
        > }[/color]

        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".[color=blue]
        >
        > //"inheriting " from Animal
        > Dog.prototype = new Animal();
        > Dog.prototype.c onstructor = Animal;[/color]

        Not required and not recommended -- the constructor is automatically
        Animal (or whatever topmost level object is utilized).
        [color=blue]
        >
        > 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?[/color]

        answered...
        [color=blue]
        >
        > thanks[/color]

        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("construc tor 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.cons tructor); // shows function Animal
        this.type = arg;

        }

        function
        Cat(arg)
        {
        alert(this.cons tructor); // 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.c onstructor
        // 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 "constructo r 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.cons tructor); // again -- will show Animal!
        this.brand = brand;
        }

        dogFood.prototy pe = 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.prototyp e = 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 "superclass es" anytime you
        wish by redeclaring the prototype:

        dogFood.prototy pe = new Dog("my pet"); // changed from "all breeds"


        var dogfood2 = new dogFood("iams") ;

        Now compare df.showAll() and dogfood2.showAl l() -- 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 *functionalitie s* 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...

        Comment

        Working...