Recursive object literals in Javascript ?

Discussion in 'Javascript' started by java, Apr 16, 2008.

  1. java

    java Guest

    Consider:

    var x = {a:3, b:x};

    alert(x.b) ==> undefined

    Question: why ?

    x is a pointer to an object, so x.b should refer
    to that same object.

    Theoretically:
    x --> some object containing
    a = 3,
    b --> x

    However, this is NOT the case. So why is
    x.b "undefined" in JS ?

    --j
     
    java, Apr 16, 2008
    #1
    1. Advertising

  2. java wrote:
    > Consider:
    >
    > var x = {a:3, b:x};
    >
    > alert(x.b) ==> undefined
    >
    > Question: why ?
    >
    > x is a pointer to an object, so x.b should refer
    > to that same object.
    >
    > Theoretically:
    > x --> some object containing
    > a = 3,
    > b --> x
    >
    > However, this is NOT the case. So why is
    > x.b "undefined" in JS ?


    The order of evaluation. The right hand side of an assignment expression
    is evaluated before the resulting value can be assigned to the left hand
    side (it has to be). So at the point of evaluation the object literal
    the - x - variable has its default - undefined - value, and so that is
    what bets assigned to the object's - b - property.

    Richard.
     
    Richard Cornford, Apr 17, 2008
    #2
    1. Advertising

  3. java

    Evertjan. Guest

    Richard Cornford wrote on 17 apr 2008 in comp.lang.javascript:

    > java wrote:
    >> Consider:
    >>
    >> var x = {a:3, b:x};
    >>
    >> alert(x.b) ==> undefined
    >>
    >> Question: why ?
    >>
    >> x is a pointer to an object, so x.b should refer
    >> to that same object.
    >>
    >> Theoretically:
    >> x --> some object containing
    >> a = 3,
    >> b --> x
    >>
    >> However, this is NOT the case. So why is
    >> x.b "undefined" in JS ?

    >
    > The order of evaluation. The right hand side of an assignment
    > expression is evaluated before the resulting value can be assigned to
    > the left hand side (it has to be). So at the point of evaluation the
    > object literal the - x - variable has its default - undefined - value,
    > and so that is what bets assigned to the object's - b - property.


    Right.

    ===========

    simply doing:

    var x = {a:3};
    x.b = x;
    alert(x.b.a); // 3

    could get interesting:

    var x = {a:3};
    x.b = x;
    alert(x.b.b.b.b.b.b.b.b.b.b.b.b.a); // 3

    and perhaps even useful in visonary recursionistic programming?

    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
     
    Evertjan., Apr 17, 2008
    #3
  4. Richard Cornford wrote:
    > java wrote:
    >> Consider:
    >>
    >> var x = {a:3, b:x};
    >>
    >> alert(x.b) ==> undefined

    >
    > The right hand side of an assignment expression
    > is evaluated before the resulting value can be assigned to the left hand
    > side (it has to be). So at the point of evaluation the object literal
    > the - x - variable has its default - undefined - value, and so that is
    > what bets assigned to the object's - b - property.


    Of course, evaluation of x on the RHS can be deferred by wrapping it
    in a closure:

    var x = {a:3, b:function(){return x;}};
    alert(x.b().a);

    Obviously that's not the same thing as what the OP was trying to do,
    but it's a common idiom in functional programming.

    Alternatively, with an implementation that supports getters, you can
    provide a getter for b that returns x:

    var x = {a:3};
    x.__defineGetter__("b",function(){return this;});
    alert(x.b.a);

    though whether that's good practice is debatable. (And in this
    particular case, I don't think this has any advantage this has over
    simply "x.b=x", as Richard suggested. If you wanted b to evaluate to
    x.a, then the getter would do something for you.)

    If you're using an implementation that supports defining getters in an
    object literal (eg sufficiently recent Mozilla Javascript), then you
    can create a closure that will automatically be evaluated, as part of
    your object literal:

    var x = {a:3, get b(){return this;}};
    alert(x.b.a);

    which achieves the same result as the OP's example. x.b is not
    actually a reference to x, of course; it just returns one when
    evaluated. Though I'm not sure whether a Javascript program can
    distinguish the two.

    --
    Michael Wojcik
     
    Michael Wojcik, Apr 18, 2008
    #4
  5. java

    J.S.Criptoff Guest

    With an implementation that supports "sharp variables" (non-standard
    notation borrowed from Common Lisp) we can write:

    var x = #1= {a: 3, b: #1#};
    alert(x.b.a); //-> 3
     
    J.S.Criptoff, Apr 18, 2008
    #5
  6. java

    Evertjan. Guest

    J.S.Criptoff wrote on 19 apr 2008 in comp.lang.javascript:

    > With an implementation that supports "sharp variables" (non-standard
    > notation borrowed from Common Lisp) we can write:
    >
    > var x = #1= {a: 3, b: #1#};
    > alert(x.b.a); //-> 3


    You cannot borrow from another language,
    [how would you return it?]
    most of us do not lisp.

    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)
     
    Evertjan., Apr 19, 2008
    #6
  7. java

    J.S.Criptoff Guest

    On 19 ÁÐÒ, 12:51, "Evertjan." <> wrote:
    > J.S.Criptoff wrote on 19 apr 2008 in comp.lang.javascript:
    >
    > > With an implementation that supports "sharp variables" (non-standard
    > > notation borrowed from Common Lisp) we can write:

    >
    > > var x = #1= {a: 3, b: #1#};
    > > alert(x.b.a); //-> 3

    >
    > You cannot borrow from another language,
    > [how would you return it?]
    > most of us do not lisp.
    >
    > --
    > Evertjan.
    > The Netherlands.
    > (Please change the x'es to dots in my emailaddress)


    Should I replace word "borrowed" with "stolen"? Anyway "sharp
    variables" do work in FF (SpiderMonkey).
     
    J.S.Criptoff, Apr 19, 2008
    #7
  8. Michael Wojcik wrote:
    > Richard Cornford wrote:
    >> java wrote:
    >>> Consider:
    >>>
    >>> var x = {a:3, b:x};
    >>>
    >>> alert(x.b) ==> undefined

    >>
    >> The right hand side of an assignment expression is evaluated before
    >> the resulting value can be assigned to
    >> the left hand side (it has to be). So at the point of
    >> evaluation the object literal the - x - variable has its
    >> default - undefined - value, and so that is what bets
    >> assigned to the object's - b - property.

    >
    > Of course, evaluation of x on the RHS can be deferred by
    > wrapping it in a closure:
    >
    > var x = {a:3, b:function(){return x;}};
    > alert(x.b().a);
    >
    > Obviously that's not the same thing as what the OP was
    > trying to do, but it's a common idiom in functional
    > programming.
    >
    > Alternatively, with an implementation that supports getters,
    > you can provide a getter for b that returns x:
    >
    > var x = {a:3};
    > x.__defineGetter__("b",function(){return this;});
    > alert(x.b.a);
    >
    > though whether that's good practice is debatable. (And in
    > this particular case, I don't think this has any advantage
    > this has over simply "x.b=x", as Richard suggested.


    It was Evertjan who posted that suggestion. I think my first suggestion
    would have been that this may be a case for using a constructor to
    create the object rather than an Object literal. I.E.:-

    var x = new SomeObj();

    function SomeObj(){
    this.b = this;
    }
    SomeObj.prototype.a = 3;

    - which does not involve creating any more additional function objects
    than your suggestion, and fewer if there are going to be more than one
    such objects created.

    > If you wanted b to evaluate to x.a, then the getter would do something
    > for you.)
    >
    > If you're using an implementation that supports defining
    > getters in an object literal (eg sufficiently recent Mozilla
    > Javascript), then you can create a closure that will
    > automatically be evaluated, as part of your object literal:
    >
    > var x = {a:3, get b(){return this;}};
    > alert(x.b.a);


    The problem with all of these non-standard language extensions is that
    while you can employ them when writing for a single known implementation
    where they are implemented they are mostly non-practical in a general
    context because they mostly constitute a syntax error where not
    implemented, and there are virtually no practical steps that can be
    taken to detect support for a syntax extension without provoking the
    syntax error wherever it does not exist.

    Richard.
     
    Richard Cornford, Apr 19, 2008
    #8
  9. Richard Cornford wrote:
    > Michael Wojcik wrote:
    >> Richard Cornford wrote:
    >>> java wrote:
    >>>>
    >>>> var x = {a:3, b:x};
    >>>>
    >>> The right hand side of an assignment expression is evaluated before
    >>> the resulting value can be assigned to
    >>> the left hand side (it has to be).

    >>
    >> Of course, evaluation of x on the RHS can be deferred by
    >> wrapping it in a closure:
    >>
    >> ...
    >>
    >> Obviously that's not the same thing as what the OP was
    >> trying to do, but it's a common idiom in functional
    >> programming.
    >>
    >> Alternatively, with an implementation that supports getters,
    >> you can provide a getter for b that returns x:
    >>
    >> ...
    >>
    >> though whether that's good practice is debatable. (And in
    >> this particular case, I don't think this has any advantage
    >> this has over simply "x.b=x", as Richard suggested.

    >
    > It was Evertjan who posted that suggestion.


    Sorry about the misattribution.

    > I think my first suggestion
    > would have been that this may be a case for using a constructor to
    > create the object rather than an Object literal.


    Agreed. In this case I was interested in the OP's question, rather
    than better ways to accomplish the same result.

    >> If you're using an implementation that supports defining
    >> getters in an object literal ...

    >
    > The problem with all of these non-standard language extensions is that
    > while you can employ them when writing for a single known implementation
    > where they are implemented they are mostly non-practical in a general
    > context because they mostly constitute a syntax error where not
    > implemented, and there are virtually no practical steps that can be
    > taken to detect support for a syntax extension without provoking the
    > syntax error wherever it does not exist.


    Agreed again, in the general case. Some of the Javascript I write
    explicitly targets specific implementations, just like some of the
    programs I write in other languages.

    --
    Michael Wojcik
     
    Michael Wojcik, Apr 19, 2008
    #9
    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. John Goche
    Replies:
    8
    Views:
    16,473
  2. n00m
    Replies:
    12
    Views:
    1,119
  3. vamsi
    Replies:
    21
    Views:
    2,088
    Keith Thompson
    Mar 9, 2009
  4. Oltmans
    Replies:
    2
    Views:
    88
  5. Keith Hughitt

    JSON: Array of object literals?

    Keith Hughitt, Jul 1, 2009, in forum: Javascript
    Replies:
    10
    Views:
    261
    David Mark
    Jul 3, 2009
Loading...

Share This Page