function declaration поднимается наверх скоупа, объявления тоже, а var объявляет локальную переменную
Ваш код в представлении интерпретатора javascript:
function f() { console.log(2) }
(function() {
var f;
f(); // f локальная и сейчас undefined
f = function() { console.log(1) } // и только тут в нее пишется ссылка на функцию
})();
f();
Второй вариант:
function f() { console.log(2) }
(function() {
f(); // f функция из родительского скоупа
f = function() { console.log(1) } // а тут она просто перезаписывается
})();
f();