Entendi agora sua pergunta.
Quando vc faz imprime o document
na verdade vc ta imprimindo a referencia ao objeto document
. No Chrome por exemplo ele mostra só #document
e uma setinha pra vc expandir e ver o resto.
Conforme vc vai abrindo as setinhas, ele vai puxando os valores live do documento. Isso quer dizer que ele nao ta mostrando o que tinha la dentro quando a referencia do document foi impressa; ele ta mostrando o que tem la dentro quando a setinha foi clicada.
E vc tem razao, se vc imprime o document no inicio da pagina, ela ainda nao gerou o HTML todo e estaria vazio. Mas como a pg carrega mto rapido, vc nao consegue ver isso, pq quanco clica na setinha o HTML ja carregou.
Da pra enxergar isso forcando um script que trave a renderizacao da pagina e ai vc consegue clicar na setinha antes e ver que ele ta vazio. So usar um alert:
console.log(document);
alert();
Executa isso, nao clica no alert e olha o #document no Console pra ver que ele ta vazio.
E ai, quando vc chama o querySelector
ele busca no HTML que esta disponivel no momento. E como vc colocou no topo, antes da declaracao do <h1>
, ele nao acha e dá erro.