Question: Why does Javascript add an extra backslash when I capture input values?

I have a standard HTML input form. The issue occurs when I enter something like \n in the input. I'm aware it's a regex that means newline, but a user may for example have it in their password, and it should remain unchanged.
The behaviour I'm observing:
const value = $('#myInput').val()
console.log(value)   // Console shows: hello\n (which is indeed what the user typed in)
const outputData = { password: value }
console.log(outputData)   // Console shows: { password: "hello\\n"}

It would be fine if it were just a display issue, but that data is being sent to the server with the double backslash, so there is a mismatch between what the user types in and what gets sent to the server (which of course breaks things).
It's also worth noting this doesn't happen (everything works as expected) when I send a request body via Postman

Why is this happening?
How can I avoid it?



Answer:
Re the code comments in the code you shared:


const value = $('#myInput').val()
console.log(value)   // Console shows: hello\n (which is indeed what the user typed in)
const outputData = { password: value }
console.log(outputData)   // Console shows: { password: "hello\\n"}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="myInput" value="hello\n">



I assume you're referring to this style of console output:

That's just the difference between how the Chrome console (and some others) displays the output when you pass it a string vs. when you pass it an object. JavaScript is not adding anything to the string. When you pass a string to console.log, it just shows the characters of the string (which in your case are h, e, l, l, o, \, and n). But when you pass it an object, it shows you something that looks like an object literal, and since the object literal contains a string literal for password, the backslash in the string literal has to be shown escaped. (Otherwise, it would be an escape character.) But there is only one backslash in the string, not two, exactly like this:


console.log("hello\\n"); // <== Notice the escaped backslash



The backslash is escaped in the string literal, because otherwise it wouldn't be a backslash, it would be an escape character changing the meaning of the next character (in this case, putting a newline in the string rather than \ and n.) There is only one backslash in the string.

It would be fine if it were just a display issue, but that data is being sent to the server with the double backslash...

Two possibilities here:

The extra backslash is being added by code you haven't shown, either the code preparing the string to send to your server, or the code on the server writing it to the database. For instance, another answer posted to this question suggested doing JSON.stringify(value), but that would add an extra backslash to it for the same reason we put on in a string literal: you have to escape backslashes in JSON strings. The extra one would be removed if the server code parsed the JSON, but it wouldn't be if the server code used the string as-is. I'm not saying you're doing that, just that it's the kind of thing you could be doing to see what you're describing.

Or — with apologies! :-) — it's possible that you're misinterpreting what you're seeing for what's in the database in the same way you misinterpeting the object literal in the console and there is actually only one backslash in the database.


Your best bet for finding out what's causing the problem is to carefully audit the code processing the string, in particular:

Check the actual value of the string with a debugger just prior to sending it to the server.
Check how you're encoding what you're sending the server.
Check exactly what your code on the server is receiving.
Check what that code is doing to the string when adding the value to the database.

Somewhere along the line, you'll either determine there isn't actually a problem (#2 above), or you'll find out what's mistakenly adding the backslash (#1 above).