constructor for a derived object is same as that of its parent

Discussion in 'Javascript' started by satyajit, Nov 29, 2006.

  1. satyajit

    satyajit Guest

    I am trying to learn the concept of constructors in ECMAScript. I
    executed following code (See execution in Rhino JavaScript shell):
    function Foo(a)
    {
    this.a = a;
    }

    function Bar(b)
    {
    this.b = b;
    }
    Bar.prototype = new Foo(1);
    var x = new Foo(2);
    var y = new Bar(3);

    Now I expect y.constructor to give me Bar, but I am getting Foo.
    Can anybody explain?

    Following the execution sequence in Rhino JavaScript shell:

    Rhino 1.6 release 5 2006 11 18
    js> function Foo(a)
    {
    this.a = a;
    }
    js> function Bar(b)
    {
    this.b = b;
    }
    js> Bar.prototype = new Foo(1);
    [object Object]
    js> var x = new Foo(2);
    js> var y = new Bar(3);
    js> x.constructor

    function Foo(a) {
    this.a = a;
    }

    js> y.constructor

    function Foo(a) {
    this.a = a;
    }

    Regards,
    Satyajit
    satyajit, Nov 29, 2006
    #1
    1. Advertising

  2. satyajit

    VK Guest

    satyajit wrote:
    > function Foo(a)
    > {
    > this.a = a;
    > }
    >
    > function Bar(b)
    > {
    > this.b = b;
    > }
    > Bar.prototype = new Foo(1);
    > var x = new Foo(2);
    > var y = new Bar(3);
    >
    > Now I expect y.constructor to give me Bar, but I am getting Foo.


    Yep... And at the same
    alert(y instanceof Bar); // true
    or (the same but more "conceptual"):
    alert(Bar.prototype.isPrototypeOf(y)); // true

    Tricky, is not it? ;-)

    I highly suggest you to read and study all samples from:

    Eric Lippert
    "The JScript Type System, Part Two: Prototypes and constructors"
    <http://blogs.msdn.com/ericlippert/archive/2003/11/06/53352.aspx>

    This rather short blog post is the *only one* source about JavaScript
    inheritance currently existing in the Internet. There can be more of
    course, but my two years search did not reveal them. Anything else I
    could find is either an erroneus crap or multi-paged revelations
    leaving you even more confusing then ever before.

    P.S. Eric Lippert is the original maker of Microsoft JScript engine.
    That doesn't mean that you have to take each his word as the final
    truth: there is a difference between a piano maker and a piano player
    :) I just thought that it should be mentioned that he is not some
    "side ECMAScript specialist".
    VK, Nov 29, 2006
    #2
    1. Advertising

  3. satyajit wrote:
    > I am trying to learn the concept of constructors in ECMAScript. I
    > executed following code (See execution in Rhino JavaScript shell):
    > function Foo(a)
    > {
    > this.a = a;
    > }
    >
    > function Bar(b)
    > {
    > this.b = b;
    > }
    > Bar.prototype = new Foo(1);
    > var x = new Foo(2);
    > var y = new Bar(3);
    >
    > Now I expect y.constructor to give me Bar, but I am getting Foo.
    > Can anybody explain?


    This has confused a lot of people but it only shows that the constructor
    property is not very intuitive respectively not set in a way that
    follows the intuition people have that think in class based terms and
    expect "instances" in JavaScript to have a property named constructor
    that points to the function constructor.

    You might want to check
    y.hasOwnProperty('constructor')
    and you will find that y does not have an own property of that name.
    That means when y.constructor is looked up that the prototype chain is
    used to look for the property and so the lookup first looks at
    Bar.prototype having a constructor property but it does not have one meaning
    Bar.prototype.hasOwnProperty('constructor')
    is false too, then follows the lookup of Foo.prototype and
    Foo.prototype.hasOwnProperty('constructor')
    is true and that constructor property has been set when the Foo function
    was created according to section 13.2 of the ECMAScript edition 3
    specification.

    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
    Martin Honnen, Nov 29, 2006
    #3
  4. satyajit wrote:
    > I am trying to learn the concept of constructors in ECMAScript. I
    > executed following code (See execution in Rhino JavaScript shell):
    > function Foo(a)
    > {
    > this.a = a;
    > }
    >
    > function Bar(b)
    > {
    > this.b = b;
    > }
    > Bar.prototype = new Foo(1);
    > var x = new Foo(2);
    > var y = new Bar(3);
    >
    > Now I expect y.constructor to give me Bar, but I am getting Foo.
    > Can anybody explain?

    <snip>

    When a function object is created it is given a - prototype - property
    and that property is assigned a value that is a reference to an object.
    That object is then given a - constructor - property that is assigned a
    reference to the function object.

    If the function object is used to construct an object the value
    currently assigned to its - prototype - property is assigned to the new
    object's internal [[Prototype]] property, which is then used as the
    first object in the new object's prototype chain. Thus this new object
    inherits a reference to the function object used as its constructor
    through its prototype chain.

    You have replaced the object originally assigned to - Bar.prototype -
    with an instance of Foo. Thus the object that had the - constructor -
    property that referred to Bar has been replaced with an object that is
    inheriting a constructor - property through its prototype chain from -
    Foo.prototype -. And when that object is assigned to the internal
    [[Prootype]] properties of objects created with - new Bar - they
    inherit its - constructor - property.

    You can mitigate that issue by doing:-

    Bar.prototype = new Foo(1)
    Bar.prototype.constructor = Foo;

    - and then new instances of Bar will inherit a - constructor - property
    that refers to - Foo -.

    However, you really should not be writing javascript code in which you
    need to test for the constructor of any objects (outside of
    experimental and testing code). There are no casting issues in
    javascript as all objects are really of a single 'class' and in a
    loosely typed language like javascript it is a necessary discipline for
    the programmer to be keeping track of the types being used and so
    situations where you need to query a type at runtime are exceptional.

    Richard.
    Richard Cornford, Nov 29, 2006
    #4
  5. Richard Cornford wrote:

    > You can mitigate that issue by doing:-
    >
    > Bar.prototype = new Foo(1)
    > Bar.prototype.constructor = Foo;
    >
    > - and then new instances of Bar will inherit a - constructor - property
    > that refers to - Foo -.


    How does that mitigate things? The original poster complained about Foo
    being returned by y.constructor and wanted Bar instead. That code above
    does not change that, unless you wanted to set
    Bar.prototype.constructor = Bar;



    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
    Martin Honnen, Nov 29, 2006
    #5
  6. Martin Honnen wrote:
    > Richard Cornford wrote:
    >
    > > You can mitigate that issue by doing:-
    > >
    > > Bar.prototype = new Foo(1)
    > > Bar.prototype.constructor = Foo;
    > >
    > > - and then new instances of Bar will inherit a - constructor - property
    > > that refers to - Foo -.

    >
    > How does that mitigate things? The original poster complained about Foo
    > being returned by y.constructor and wanted Bar instead. That code above
    > does not change that, unless you wanted to set
    > Bar.prototype.constructor = Bar;


    You are right. I intended to type Bar and typed Foo instead.

    Richard.
    Richard Cornford, Nov 29, 2006
    #6
  7. Peter Michaux, Nov 29, 2006
    #7
  8. satyajit

    VK Guest

    Peter Michaux wrote:
    > You may enjoy this tutorial
    >
    > http://kevlindev.com/tutorials/javascript/inheritance/index.htm
    >
    > And at least the first of these three videos
    >
    > http://yuiblog.com/blog/2006/11/27/video-crockford-advjs/


    Video is good (though the downstream from the Yahoo server seems poor
    as it chocks even on my DSL).

    The inheritance article (the first one) is a rather dangerous reading.
    It is one of countless "C++ over JavaScript" tutorials: a little
    preface about prototype inheritance (just few words do not make a
    C++'er too much bored) and then quickly move onto the main part: how to
    build inheritance in the "conventional proper" way and do not be
    bothered with that stupid prototypes anymore. Such articles constitute
    90% of "inheritance in JavaScript" sources, but this one admittedly is
    of much better quality than many of what I've seen.

    I mean hell - I use "classy" emulation in JavaScript left and right
    myself because it's often more easy and quickly in a mixed environment.
    But if anyone is targeted to understand how is it *really* ticking
    (even if never come to it again and just stick to say prototype.js)
    then such articles should be read only after the one I posted.
    VK, Nov 29, 2006
    #8
  9. In article <>,
    Richard Cornford <> writes

    <snip>
    >However, you really should not be writing javascript code in which you
    >need to test for the constructor of any objects (outside of
    >experimental and testing code). There are no casting issues in
    >javascript as all objects are really of a single 'class' and in a
    >loosely typed language like javascript it is a necessary discipline for
    >the programmer to be keeping track of the types being used and so
    >situations where you need to query a type at runtime are exceptional.


    To add to that, the 'constructor' property is like 'with' and two-digit
    year numbers : each seemed a good idea at the time, but in practice each
    causes a lot of confusion and can be done better a different way.

    John
    --
    John Harris
    John G Harris, Nov 29, 2006
    #9
  10. satyajit

    satyajit Guest

    Martin Honnen wrote:
    > Richard Cornford wrote:
    > > You can mitigate that issue by doing:-
    > >
    > > Bar.prototype = new Foo(1)
    > > Bar.prototype.constructor = Foo;
    > >
    > > - and then new instances of Bar will inherit a - constructor - property
    > > that refers to - Foo -.

    >
    > How does that mitigate things? The original poster complained about Foo
    > being returned by y.constructor and wanted Bar instead. That code above
    > does not change that, unless you wanted to set
    > Bar.prototype.constructor = Bar;


    Thanks VK, Martin, and Richard for very explanations. Got the reason
    after I read Eric Lippert blog.

    I did not want to set "Bar.prototype.constructor = Bar;" but was trying
    to find out how the constructor and prototypes work. The version of
    ECMAScript standard that I got originally from ECMA's site was ECMA-262
    standard and that did not have reference to instanceof and
    isPrototypeOf(). Getting these concepts from the standard was very
    difficult.

    However one thing I noticed in the ECMA standard that the String
    behaves differently when called as constructor and as function. I
    wanted to explore how to do that for my own functions that can be used
    as constructor or as conversion type. I tried to make sense of some
    earlier posts but could not do so.

    - Satyajit
    satyajit, Nov 30, 2006
    #10
  11. satyajit

    VK Guest

    satyajit wrote:

    > The version of
    > ECMAScript standard that I got originally from ECMA's site was ECMA-262
    > standard and that did not have reference to instanceof and
    > isPrototypeOf(). Getting these concepts from the standard was very
    > difficult.


    The current standard is ECMA-262 3rd edition, so you must be reading
    ECMA-262 2nd edition (same standard but the obsolete edition). The 3rd
    (current) edition as available at
    <http://www.ecma-international.org/publications/standards/Ecma-262.htm>

    Please note though that - despite of what the name implies - this
    standard describes an ECMAScript-compliant *script engine* so primary
    targeted to UA producers and not to the end developers. This way
    learning the JavaScript programming by ECMA-262 specs is like learning
    to drive by car's technical specs: theoretically possible, practically
    very difficult :)

    >From the online resources linked at

    <http://www.jibbering.com/faq/#FAQ3_2> I would suggest first MSDN
    JScript 5.6 documentation as the most consistent (though still not
    bug-free):
    <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/29f83a2c-48c5-49e2-9ae0-7371d2cda2ff.asp>

    It is available for download (.chm help file, 2.8Mb) at
    <http://www.microsoft.com/downloads/details.aspx?familyid=01592C48-207D-4BE1-8A76-1C4099D7BBB9>
    A "Genuine Windows validation" is required, also chm help files need IE
    installed to be viewed - so alas this download is useless for many
    developers.

    (JScript 5.6 is the one running on IE 6 and - with one minor
    modification - on IE 7. It corresponds to Mozilla JavaScript 1.5 minus
    all Mozilla/Microsoft extensions).


    > However one thing I noticed in the ECMA standard that the String
    > behaves differently when called as constructor and as function.


    I'm not sure if I fully understand this statement. There can be string
    primitive value and string object in JavaScript: the first one created
    implicitly out of string literal, the second one created explicetly by
    using String constructor: new String(value) The explicit String
    constructor is very rarely used in JavaScript.

    > I wanted to explore how to do that for my own functions that can be used
    > as constructor or as conversion type. I tried to make sense of some
    > earlier posts but could not do so.


    In JavaScript the call context defines everything: so the very same
    function can act as an object constructor or as a regular subroutine,
    depending on how did you call it. Some formal description of your
    actual task would be helpful.
    VK, Dec 1, 2006
    #11
  12. satyajit

    satyajit Guest

    VK wrote:
    <snip>
    > In JavaScript the call context defines everything: so the very same
    > function can act as an object constructor or as a regular subroutine,
    > depending on how did you call it. Some formal description of your
    > actual task would be helpful.


    Thanks for the resources. To give an example (not a real example) of
    what I was trying to find out is as follows:

    function MimeType(string extension)
    {
    if ( /* its a constructor - this is what I want to know how to
    check. */ )
    {
    // initialize MimeType. For jpeg, description is 'image/jpeg'
    // Assume that getDescriptionFromExtension() returns a string
    // with appropriate description
    this.description = getDescriptionFromExtension(extension);
    // other initializers..
    }
    else return getDescriptionFromExtension(extension);
    }

    I could use it like
    var img1 = new MimeType(".jpeg");
    img1.description would then be "image/jpeg"

    another probable usage:

    if ("image/jpeg" == MimeType(extension));

    Any quick ideas?

    Thanks.
    -Satyajit
    satyajit, Dec 5, 2006
    #12
  13. satyajit

    VK Guest

    satyajit wrote:
    > To give an example (not a real example) of
    > what I was trying to find out is as follows:
    >
    > function MimeType(string extension)
    > {
    > if ( /* its a constructor - this is what I want to know how to
    > check. */ )
    > {
    > // initialize MimeType. For jpeg, description is 'image/jpeg'
    > // Assume that getDescriptionFromExtension() returns a string
    > // with appropriate description
    > this.description = getDescriptionFromExtension(extension);
    > // other initializers..
    > }
    > else return getDescriptionFromExtension(extension);
    > }
    >
    > I could use it like
    > var img1 = new MimeType(".jpeg");
    > img1.description would then be "image/jpeg"
    >
    > another probable usage:
    >
    > if ("image/jpeg" == MimeType(extension));
    >
    > Any quick ideas?


    The first one is that I'm not excited by this approach ;-) IMO using
    the same entity as object constructor and as subroutine depending on
    circumstances is a bad practice: even if the used language technically
    allows it. It obfuscates the source and it promises many problems with
    inheritance (if anyone ever extends your library). You may flush my
    opinion out though.

    If function is called as constructor, [this] points to the newly
    created object instance. (That's if no one is trying to cheat on your
    program by substituting context: say by using MimeType.call(null,
    args);
    Otherwise [this] will point to the Global context which is equal to the
    current window object in comparison operations (that's again for a
    plain-vanilla situations without any special cases).
    So if you insist on the current approach, you may check this == self :

    function MimeType(ext) {
    if (this == self) {
    // presumably called as simple function
    return 'foobar';
    }
    else {
    // presumably called as constructor
    this.description = 'foobar';
    }
    }

    var foo = new MimeType();
    var bar = MimeType();

    alert(foo.description); // 'foobar'
    alert(bar); // 'foobar'


    P.S. I would still disassemble constructor from subroutine. Just try -
    you may like it :)
    VK, Dec 5, 2006
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    393
    myork
    May 23, 2007
  2. Replies:
    1
    Views:
    385
    Victor Bazarov
    May 23, 2007
  3. thunk
    Replies:
    1
    Views:
    303
    thunk
    Mar 30, 2010
  4. thunk
    Replies:
    0
    Views:
    469
    thunk
    Apr 1, 2010
  5. Replies:
    0
    Views:
    136
Loading...

Share This Page