This is due to the function being DATALENGTH and not LEN. LEN measures "characters", while DATALENGTH measures actual bytes used to store the value. NVARCHAR is Unicode (via the UTF-16 Little Endian encoding) which is 2 or 4 bytes per "character" (with the most commonly used characters being the 2-byte variety). Hence 4000 NVARCHAR characters (assuming that they are all 2-byte characters), takes up 8000 bytes. VARCHAR (without the upper-case "N" prefix on the string literal) is 1 or 2 bytes per character (the vast majority of the time being just 1 byte), hence 4000 VARCHAR characters (assuming that they are all 1-byte characters), takes up just 4000 bytes.
The reason that you see the output you are seeing for those 4 queries is due to "Datatype Precedence". The datatypes in a particular operation need to match, so lower-precedence types will implicitly up-convert to the highest precedence type being used. NVARCHAR is higher than VARCHAR, hence VARCHAR values will implicitly convert to NVARCHAR to complete the operation.
The second query (where the upper-case "N" has been removed from the string literal, thus making it a VARCHAR(8000) ), returns 16,000 due to the REPLICATE operation returning 8000 VARCHAR characters which then get implicitly converted into NVARCHAR, which uses 2 bytes per each of those same characters.
The third query (using the upper-case "N", but the variable is now VARCHAR instead of NVARCHAR), returns 4000 due to the REPLICATE, still being of type NVARCHAR(4000), returns 4000 characters, which initially take up 8000 bytes, but in the end are converted into VARCHAR (due to that being the datatype of the variable) which only requires 1 byte per each of those characters.
The fourth query (no upper-case "N" and the VARCHAR variable) returns 8000 due to the REPLICATE operation returning 8000 VARCHAR characters (remember 'X' is interpreted as being VARCHAR(8000) ) which are then stored in a VARCHAR variable, which does not change anything, and these 8000 characters still require one byte per each character.
Does that all make sense?
Take care, Solomon...