Все правильно, он и будет возвращать undefined. Я думаю, что Вы не верно трактуете выполнение setTimout(). Вот в этом участке
else {
setTimeout(function() {
opacity -= 0.1;
console.log(opacity);
return userFadeout2(el,delay,opacity.toFixed(1));
},delay);
}
не будет ожидания выполнения setTimeout, он создаст отложенное выполнение и вернет undefined, т.к. другого ничего не указано. Дальше setTimeout запустит Вашу функцию userFadeout2, но она так же, если opacity будет не равно 0, вернет undefined.
Лень проверять, но кажется setTimeout возвращает delay и Ваш return userFadeout2 не сработает как Вы хотите. Вам нужно сделать что-то подобие
else {
$.when(setTimeout(function() {
console.log("pause");
},delay)
).then(function(){
opacity -= 0.1;
console.log(opacity);
userFadeout2(el,delay,opacity.toFixed(1));
});
}
Это без проверок с ходу, как пример, думаю мысль уловите.