The key to this line is:
chineseBox.content = chineseBox;
This gives chineseBox link to itself. So:
show(chineseBox.content === chineseBox);
You should see that this also outputs true .
Therefore, 'content' is in chineseBox , as well as chineseBox.content (and chineseBox.content.content , etc.), because they are all the same objects that have the content property.
Look at your second and third examples. Why does one give a TypeError and 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 check whether the specified property ("content s ") is specified in the specified object, you first need to evaluate what the object is. You get a type error because chineseBox.contents is undefined and therefore you cannot access the content property because there is no access to the object.
Compare this with a third example:
show("contents" in chineseBox.content.contents);
Now the in operator will at least be further than in the second example. The chineseBox.content property exists, and access to its contents s gives you undefined . So there are no errors there. But then you get an error with the in keyword because you cannot check if the property is in undefined .
In other words, in the second example, this is similar to how you ask: "Are there any elves in Santa's house?" Santa does not exist, so there is no place like "Santa House". In the third example, this is more like what you ask: "Where is the oval office in Obama's brown house?" Obama exists, but he does not have a brown house.