It works because by default, all elements that have ids are dumped on the window object, using their id as their property name. Some browsers do the same with name. Since the window object is the global object in browsers, those seemingly-free-standing variables are resolved as properties of window.
It's not a good thing to rely on, because the global namespace is very crowded and it's really easy to shadow those. For instance:
function preview() { }
Now that element with the id preview isn't available as a global symbol anymore, because I've shadowed it with a function. Or
var preview;
Boom, it's gone.
Hence using document.getElementById and such when you're looking up elements.
Re your comments below:
When I inspect the window object I can't find the property preview. Once I place a breakpoint in the function why however, window.preview suddenly is defined. Any idea how that works?
I just added window.preview as a watch expression, it returns undefined untill I hit the brekpoint.
I would expect the properties to get created as those elements were parsed. So it would depend on when you stopped and looked at window: If you were looking at it before the parser reached those DOM elements, those properties would be undefined. And that's what I see with this page:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>ScratchPad</title>
</head>
<body>
<script>
debugger;
</script>
<div id="testelement"></div>
<script>
debugger;
</script>
</body>
</html>
As of the first debugger; statement, a watch (also using Chrome's devtools) on window.testelement shows undefined, but as of the second debugger; statement, it shows the div element.