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

Recursive object literals in Javascript ?

P: n/a
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

Jun 27 '08 #1
Share this Question
Share on Google+
6 Replies


P: n/a
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

Jun 27 '08 #2

P: n/a
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
Jun 27 '08 #3

P: n/a
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)
Jun 27 '08 #4

P: n/a
On 19 , 12:51, "Evertjan." <exjxw.hannivo...@interxnl.netwrote:
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).
Jun 27 '08 #5

P: n/a
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.
Jun 27 '08 #6

P: n/a
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

Jun 27 '08 #7

This discussion thread is closed

Replies have been disabled for this discussion.