Erro no código JavaScript

Oi tudo bem, estou fazendo um projeto em HTML e JavaScript só que aparece esse erro: Uncaught TypeError: Cannot read properties of null (reading ‘addEventListener’)
at script.js:2:7
segue ai o meu código tanto em JavaScript quanto em HTML
JavaScript:

var botao = document.querySelector('input#con')
botao.addEventListener('click', contar)
function contar(){
    var ini = document.getElementById('txti')
    var fim = document.getElementById('txtf')
    var pas = document.getElementById('txtp')
    var res = document.getElementById('res')
    if(ini.value.length == 0){
        alert('[ERRO] Você não colocou o valor do inicio, por favor coloque e tente novamente [ERRO]')
    } else if(fim.value.length == 0){
        alert('[ERRO] Você não colocou o valor do fim, por favor coloque e tente novamente [ERRO]')
    } else if(pas.value.length == 0){
        alert('[ERRO] O valor do passo é 0 e ele não pode ser 0, altere os valores e tente novamente [ERRO]')
    } else if(ini > fim){
        alert('[ERRO] O valor do inicio é maior que o fim, altere os valores e tente novamente[ERRO]')
    } else{
        res.innerHTML('Contando: ')
        var i = Number(ini.value)
        var f = Number(fim.value)
        var p = Number(pas.value)
        for(var c = i;c <= f; c += p){
            res.innerHTML = `${c}`
        }
    }
}

HTML:

*<!DOCTYPE html>*
*<html lang="pt-BR">*
*<head>*
*    <meta charset="UTF-8">*
*    <meta http-equiv="X-UA-Compatible" content="IE=edge">*
*    <meta name="viewport" content="width=device-width, initial-scale=1.0">*
*    <title>Super Contador</title>*
*    <script src="script.js"></script>*
*    <link rel="stylesheet" href="style.css">*
*    *
*</head>*
*<body>*
*    <header>*
*        <h1>Vamos contar</h1>*
*    </header>*
*    <section>*
*        <div id="dados">*
*            <p>Inicio: <input type="number" name="inicio" id="txti"></p>*
*            <p>Fim: <input type="number" name="fim" id="txtf"></p>*
*            <p>Passo: <input type="number" name="passo" id="txtp"></p>*
*            <p><input type="button" value="Começar" id="con"></p>*
*        </div>*
*        <div id="res">*
*            Iniciando a contagem...*
*        </div>*
*    </section>*
*    <footer><p>&copy; CanalMistoJH</p></footer>*
*</body>*
*</html>*

Mova a tag <script> presente na tag <head> do seu documento HTML, para o final do mesmo, ficando como abaixo.

...
</html>
<script src="script.js"></script>

index.html

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Super Contador</title>   
</head>
<body>
    <header>
        <h1>Vamos contar</h1>
    </header>
    <section>
        <div id="dados">
            <p>Inicio: <input type="number" name="inicio" id="txti"></p>
            <p>Fim: <input type="number" name="fim" id="txtf"></p>
            <p>Passo: <input type="number" name="passo" id="txtp"></p>
            <p><input type="button" value="Começar" id="con"></p>
        </div>
        <div id="res">
            Iniciando a contagem...
        </div>
    </section>
    <footer><p>&copy; CanalMistoJH</p></footer>
    <script src="script.js"></script> 
</body>
</html>

Ponha o <script src="script.js"></script> no final de <body>...</body>. Assim o JavaScript é chamado após os elementos terem sido inseridos no DOM.

script.js

var botao = document.querySelector('input#con')
botao.addEventListener('click', contar)
function contar(){
    var ini = document.getElementById('txti')
    var fim = document.getElementById('txtf')
    var pas = document.getElementById('txtp')
    var res = document.getElementById('res')
    if(ini.value.length == 0){
        alert('[ERRO] Você não colocou o valor do inicio, por favor coloque e tente novamente [ERRO]')
    } else if(fim.value.length == 0){
        alert('[ERRO] Você não colocou o valor do fim, por favor coloque e tente novamente [ERRO]')
    } else if(pas.value.length == 0){
        alert('[ERRO] O valor do passo é 0 e ele não pode ser 0, altere os valores e tente novamente [ERRO]')
    } else if(ini > fim){
        alert('[ERRO] O valor do inicio é maior que o fim, altere os valores e tente novamente[ERRO]')
    } else{
        res.innerHTML = 'Contando: '
        var i = Number(ini.value)
        var f = Number(fim.value)
        var p = Number(pas.value)
        for(var c = i;c <= f; c += p){
            res.innerHTML += `${c}`
        }
    }
}

Você escreveu res.innerHTML('Contando: '), mas o certo deveria ser res.innerHTML = 'Contando: '.

E creio que você quis dizer

res.innerHTML += `${c}`

em vez de

res.innerHTML = `${c}`

Um dos problemas comuns para quem começa a trabalhar com JavaScript é entender os problemas de concorrência que surgem entre o DOM e a engine JavaScript.

Seu elemento botao não teve tempo suficiente para existir antes de o JS executar:

botao.addEventListener('click', contar)

Existem diversas formas de se resolver isso, mas acredito que a forma mais simples, sem ter de recorrer a await/async, observables, promises, etc, é colocar no seu HTML:

<p><input type="button" value="Começar" id="con" onclick="contar()"></p>

Além disso, como o @HMSLIMA comentou, res.innerHTML('Contando: ') está errado e deve ser res.innerHTML = 'Contando: '.

Porque não mover a tag script para fora da tag head

Você também pode deixar para carregar o código após a página terminar totalmente de carregar, movendo o carregamento do script para o fim do documento, entretanto, dessa forma, você não poderá explorar os benefícios de se user o atributo async ou defer na tag script, dentre eles, baixar o script enquanto a página carrega.

4 curtidas