Search code examples
javascriptjquerylinefeed

"\n" being treated as a string literal in JavaScript


I have a select tag with an option tag that has a value of "\n". When that option is selected and I get the value using jQuery, JavaScript seems to be treating it as a string literal and not interpreting it as a linefeed.

I have tried escaping, unesacping, escaping then unescaping, using the jQuery htmlEncoding technique, the jQuery htmlDecoding technique, and even tried concatenating with an empty string. I'm pulling my hair out. This should be so simple.

At least 5 workarounds pop into my head almost imediately with various levels of elegance, but at this point, I'm more interested in why this behavior exists. Is there something simple I'm missing? My real question is "why does JavaScript treat a string of \n one way in one context, but differently in another", not "how do I just get it to work".

Here is the code

Html

<select id="delimiter">
  <option value="\n">New Line</option> <!--This should produce a linefeed-->
  <option value=",">, (Comma)</option>
  <option value=";">; (Semicolon)</option>
  <option value="\t">Tab</option>
</select>
<button  onclick="doit()">
  Check It
</button>

JavaScript

function doit(){
  var delimiter = $("#delimiter").val();

  console.debug("\n"); //produces an actual linefeed character
  console.debug(delimiter); //this produces the string "\n"
}

I have a codepen of it here: https://codepen.io/codysechelski/pen/MoJKMB?editors=1111


Solution

  • "why does JavaScript treat a string of \n one way in one context, but differently in another"

    First you should understand that string literal is not actual string in memory but a part of js syntax to create strings. So escape sequences starting with "\" character signals to js engine to treat next char in different way.

    HTML doesn't have this special syntax. So "\" is just "\" and "\n" is "\n". When this string cross html-js boundary via DOM API (which is not a part of js syntax) it remains the "same" two letter string.

    By the way there are different ways to encode new line in js that produces the same string in memory

    const withEscSequence = '\n'
    
    // es2015
    const usingStringTemplate = `
    `
    // directly from char code
    const fromCharCode = String.fromCharCode(10)
    
    // using unicode escape sequence
    const unicodeEscSequence = '\u000A'
    
    // using hex escape sequence
    const hexEscSequence = '\x0A'
    
    
    console.log(withEscSequence === usingStringTemplate, withEscSequence === fromCharCode, withEscSequence === unicodeEscSequence, withEscSequence ===  hexEscSequence)