\edef expands the argument, whereas \let doesn't. Here is an example to illustrate the difference:
\def\txt{a}
\def\foo{\txt}
\let\bar\foo
\bar -> a
\def\txt{b}
\bar -> b
However,
\def\txt{a}
\def\foo{\txt}
\edef\bar{\foo}
\bar -> a
\def\txt{b}
\bar -> a
There are also other differences, say, the arguments and so on. But how to expansion may be the most important(?).
This is an interesting question. May I expand the question further more?
What is the difference between \let and \expandafter\def\expandafter\foo\expandafter ? Do they always behave the same?
\def\txt{bar}
\def\foo{\txt}
\expandafter\def\expandafter\bar\expandafter{\foo}
\let\BAR\foo
{\tt \string\bar = \meaning\bar}\par
{\tt \string\BAR = \meaning\bar}
Sneaky inline answer to this rhetorical question, since I wrote the original question :)
If you are doing this on macros that take no arguments, then the difference between them is negligible. OTOH, you cannot use the \expandafter\def... construct if you're trying to copy the definition of a macro that takes arguments.
In fact, this brings to light one of the aspects that I was hoping people would discuss here. \let creates a literal copy of a macro at the instant that it is executed, whereas \edef will take the contents of the macro and expand it recursively to create a new macro entirely. When you are only using the macros as places to store data (such as \def\name{Will}) then the differences are largely inconsequential, but when the macros are being used as ‘functions’ that take arguments or have contents that have various expansion restrictions applied to it (with \protected, \noexpand, and so on) then the differences can be very important indeed.
\count1=0 \def\resA{\count1=10 \the\count1} \edef\resB{\count1=10 \the\count1}At definition time\the\count1can be expanded, but (it seems) the assignment cannot. Thus, while both macros assign 10 to\count1\resB will produce a 0 in the output. – somloigaluska Jan 04 '21 at 15:10\edef.\the\count1, on the other hand, is expandable and expands to the value of the counter (which at the time the\edefis executed, is zero because the assignment in the\edefwasn't carried out). I'm afraid this doesn't quite answer the question, so it would be better suited as a comment – Phelype Oleinik Jan 04 '21 at 16:33