bigbitecode
bigbitecode

Reputation: 263

Understanding "in" keyword in Javascript

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?

Upvotes: 4

Views: 137

Answers (2)

Dan Tao
Dan Tao

Reputation: 128327

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.

Upvotes: 6

John Kugelman
John Kugelman

Reputation: 361605

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'.)

Upvotes: 3

Related Questions