I'll have to make this an answer only because I cannot attach screen shots to comments, but I do not see this behaviour.
- I confirm that the
window.uuid
variable does not exist on window
.
- I add the event listener, and get the expected first
undefined
from registering it.
- Then I click out of the tab (the first
visibilitychange
event), and get the second undefined
and the value set for window.uuid
, both logged from the listener.
- I click back into the tab, firing the second
visibilitychange
event, and get the uuid logged twice.
- Typing
window.uuid
into the console returns the global uuid value.

I suspect the confusion may lay in the way you are attaching the event listener.
EDIT:
With the following test page:
<html>
<head>
<script>
window.addEventListener("visibilitychange", function(e) {
console.dir(window);
console.log(window.uidd)
window.uidd = window.uidd || (new Date).getTime() + Math.random()
console.log(window.uidd)
})
</script>
</head>
<body></body>
</html>
I do see this behaviour. You need to access the property using this.uuid
, rather than window.uuid
, even though simply typing window
will show the .uuid
property.
Curiously, when I replace your test with this static assignment:
window.addEventListener("visibilitychange", function(e) {
window.foo = window.foo || "bar";
})
it does work, and I can see the expected value of window.foo
directly in the console.
I, too, am curious, and asked the Chrome team. I'll update this answer if someone from there doesn't answer directly.