A principal diferença entre os dois comandos no JavaScript e que deve ser muito bem observadi para evitar aqueles erros chatos de serem encontrados é no que tange ao segundo argumento de cada função, e como ele influencia o retorno destas funções.
No caso do substring, o segundo argumento é o índice no qual se deve parar (não incluindo a si mesmo).
Já com o substr, o segundo argumento indica o tamanho máximo a ser retornado.
Maiores detalhes:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/substr
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/substring