"We have no idea what code is going to be re-used where, so it's better to try to make sure it's easier to plug code into other unexpected places."
This statement is, alas, intrinsically a contradiction. If you do not know the dimension upon which you will be reusing a function, you can not abstract it successfully.
This is not to say you can't write good code, that is solid from a DRY perspective, that will be easy to abstract later if you need to, but you're better off doing exactly that, just writing good code that you could abstract later if you need to, than trying to guess.
That said, I'm a bit of a hypocrite and believe that a senior developer actually should have limited abilities to predict how code will develop over time. It can never be perfect, but some things are just blindingly obvious and there's no point in pretending otherwise. However, I want to make the point strongly that this is something you learn after years of writing your code with DRY and YAGNI in mind... it is far better to stay simple and then learn from experience how one might be able to make certain limited predictions (and how to mitigate the extra expense if you're wrong!) than try to pretend as a junior developer that one know where things are going.
Going down another important path, I'm about to say something that sounds like a joke but is actually quite serious. The maximally generic way of writing something in Javascript looks like this:
function plugYourStuffIn(s) { eval(s); }
You can do Anything You Want (TM)! Seriously, it's incredibly generic and powerful! It also does absolutely nothing useful. These are, inextricably, two sides of the same coin.
"Generic" intrinsically carries with it the idea of "doesn't do much". I've actually developed a near-reflexive twitch when I hear a system described as "generic" at work like it's a good thing. The act of making something generic requires you to rip out assumptions, rip out functionality to turn it into plugins, reduce the prerequisites the code requires and reduce the postconditions the code promises. Thing is, those are exactly the things we want out of our code! There's a time and place for making things "generic" but I think developers far too frequently overestimate the value it provides, because you sure can put an awful lot of work into writing code that assumes nothing, expects nothing, and provides little more than a suggested structure, but manages to spend many thousands of lines of code doing so.
Absolutely you can go too far the other way and produce brittle code that has requirements that are far too complex and makes incredibly complicated promises (that it probably fails at too)... well, I never promised programming at scale would be easy. It's a balancing act in n-dimensional space not for the faint of heart.
Indeed, when I phrase it this way, it's not hard to imagine that many of our modern problems with "bloat" and slow, overcomplicated code, ultimately stems from far, far too many layers of "generic" code and far too little code that actually does something.