In my attempt to really understand Javascript, rather than being a copy and paste Javascript googler, I'm going through Eloquent Javascript E-book and I happen to cross the following example:
var chineseBox = {};
chineseBox.content = chineseBox;
show("content" in chineseBox);
show("content" in chineseBox.content);
Surprisingly, they both output true
. The book itself claims, "The operator in
can be used to test whether an object has a certain property. It produces a boolean."
I understand that show("content" in chineseBox);
is looking for a content
property which it does have, its value being chineseBox
. However, why does the second show()
work?
To test further, I tried:
show("content" in chineseBox.content.content); //true
show("contents" in chineseBox.contents.content); //type error: undefined
show("contents" in chineseBox.content.contents); // invalid "in" operand
Question is basically, variable chineseBox{} doesn't have content property... or does it?
The key is this line:
chineseBox.content = chineseBox;
This gives chineseBox
a reference to itself. So:
show(chineseBox.content === chineseBox);
You should see this will also output true
.
Therefore 'content'
is in chineseBox
as well as chineseBox.content
(and chineseBox.content.content
and so on) because they're all the same object, which does have a content
property.
Let's look at your second and third examples. Why does one give a TypeError
while the other complains about an invalid in
operand?
In the second example, you have:
show("contents" in chineseBox.contents.content);
In order for the in
operator to test whether the specified property ("contents") is in the specified object, it first has to evaluate what that object is. You get a type error because chineseBox.contents
is undefined
, and so you can't access its content
property because there's no object to access.
Contrast this with the third example:
show("contents" in chineseBox.content.contents);
Now here, the in
operator at least gets farther than it did in the second example. The chineseBox.content
property does exist, and accessing its contents property gives you undefined
. So there is no error there. But then you get an error with the in
keyword itself because you can't check if a property is in undefined
.
In other words, in the second example it's like you're asking "Are there any elves in Santa's house?" Santa doesn't exist, so there is no such place as "Santa's house." In the third example it's more like you're asking "Where is the oval office in Obama's brown house?" Obama exists, but he doesn't have a brown house.
chineseBox.content = chineseBox;
Because of the self-reference, notice that chineseBox
is the same object as chineseBox.content
. Meaning chineseBox
, chineseBox.content
, chineseBox.content.content
, chineseBox.content.content.content
, ad infinitum, all refer to the same object.
show("content" in chineseBox);
show("content" in chineseBox.content);
show("content" in chineseBox.content.content);
show("content" in chineseBox.content.content.content);
show("content" in chineseBox.content.content.content.content);
show("content" in chineseBox.content.content.content.content.content);
(In your tests, beware the difference between content
and contents
with an 's'.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With