Recursive object literals in Javascript ?

J

java

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
 
R

Richard Cornford

java said:
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.
 
E

Evertjan.

Richard Cornford wrote on 17 apr 2008 in comp.lang.javascript:
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?
 
M

Michael Wojcik

Richard said:
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.
 
J

J.S.Criptoff

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
 
E

Evertjan.

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.
 
J

J.S.Criptoff

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.

Should I replace word "borrowed" with "stolen"? Anyway "sharp
variables" do work in FF (SpiderMonkey).
 
R

Richard Cornford

Michael said:
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.
 
M

Michael Wojcik

Richard said:
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.
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top