Is the difference here that TOTP/HOTP is entered by the user, while U2F is entered automatically?
The corresponding private key is stored on the token indexed in part by the requesting domain, which is supplied by the browser during an auth request. It is because of browser participation that a MITM domain would not be able to ask the token to answer the challenge with the correct key handle.
The actual implementation can differ from what's described above, see Yubico's description of their key wrapping scheme if you want more detail: