I'm strongly against the last "hack". It works in an isolated environment for a very specific case. Named access on the Window object is more of a leakage than an actual feature. I'm amazed it made it to the official specification. The reasons why this is not advisable:
In a real-world case, you can easily lost track of what the global variable means and does. This approach doesn't give any context on where the object comes from. You'll have to specifically track the source, in this case the HTML file and know about Named window access and how it works. I can only imagine how much pain and lost time this can bring.
Consider the following example:
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<p id=paragraph>Im a paragraph, look at me!</p>
<script>
const paragraph = 'Hello';
console.log(paragraph); // "Hello"
</script>
</body>
</html>
The variable value overwrites the previously assigned value, thus changing the whole logic.
Another example:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>Hello There!</h1>
<p id=document>Im a paragraph, look at me!</p>
<script>
console.log(document); // The global document object
</script>
</body>
</html>
The above code won't work the same way as in the previous example. document is created before parsing the HTML and it cannot be overwritten. So anyone who expects to see the HTML Element logged will be left disappointed. Even worse, what happens if you assign it that way:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>Hello There!</h1>
<p id=paragraph>Im a paragraph, look at me!</p>
<p id=text>Im a paragraph, look at me!</p>
<script>
const text = paragraph;
</script>
</body>
</html>
The lack of consistency makes this approach so error-prone, that can easily be described as an anti-pattern. So my advice would be to not use it.