Q:

Javascript declarar variaveis fora da função

Eu só quero a soma desses dois números, funciona quando eu declaro as variáveis dentro da função, por que não está funcionando assim? Estou recebendo NaN.
<form>
    <input type="number" id="num1">
    <input type="number" id="num2">
    <input type="button" value="oi" onclick="calpp()">
</form>
<script>
    var x = parseInt(document.getElementById('num1').value, 10);
    var y = parseInt(document.getElementById('num2').value, 10);

    function calpp(){
        alert(x+y);
    }
</script>

A:

O problema é a sequência de execução do JavaScript.
Neste seu código, quando o navegador carrega e processa seu HTML, ele coloca na tela os 2 inputs, e em seguida processa a tag script e executa o código que está lá dentro.
Neste momento, ele já pega o conteúdo dos inputs e armazena nas variáveis, porém a página acabou de carregar e o usuário ainda não fez nenhuma interação, logo os campos estão vazios, então ele converte "vazio" para inteiro e armazena nas variáveis x e y.
Quando o usuário clica no botão, ele apenas recupera esses valores que já estão fixos como inválidos (pois foi processado no carregamento da página) e o cálculo dá errado.
Você consegue perceber isso se já atribuir um valor inicial nos inputs:

  var x = parseInt(document.getElementById('num1').value, 10);
  var y = parseInt(document.getElementById('num2').value, 10);

  function calpp(){
      alert(x+y);
  }
<form>
    <input type="number" id="num1" value="5">
    <input type="number" id="num2" value="3">
    <input type="button" value="oi" onclick="calpp()">
</form>

Com os valores iniciais seu código funciona, mas se o usuário altera ele vai ficar para sempre com os valores iniciais pois as linhas que recupera os valores dos inputs e salva nas variáveis já foi executado quando a página foi carregada.
Por isso que quando você move para dentro da função dá certo! Quando está dentro da função e você clica no botão, os valores são recuperados na hora do input, portanto o valor que está digitado lá naquele momento.
É importante entender esse fluxo de execução do HTML, JavaScript e CSS para evitar esse tipo de situação.
Por fim, seu código com a correção:

// Podemos até declarar as variáveis fora da função
var x;
var y;

function calpp(){
  // Mas devemos sempre recuperar os dados do estado atual da aplicação
  x = parseInt(document.getElementById('num1').value, 10);
  y = parseInt(document.getElementById('num2').value, 10);
  
  // E por fim exibi-los
  alert(x+y);
}
<form>
    <input type="number" id="num1">
    <input type="number" id="num2">
    <input type="button" value="oi" onclick="calpp()">
</form>

