Why split the ` is not the only character sequence that can close a ` – Mathias Bynens Jun 29 '11 at 10:58

  • 11
    @Mathias: `<\/script>` is fine in this case, but it would only work in HTML; in XHTML without extra CDATA section wrapping, it's still a well-formedness error. Also you can use `\x3C` in inline event handler attributes where `<` would also be invalid in both HTML and XHTML, so it has a wider applicability: if I were choosing one, easily-automated way to escape sensitive characters in JS string literals for all contexts, that's the one I'd go for. – bobince Jun 29 '11 at 19:39
  • 3
    In HTML, `<` can be used in inline event handler attributes. http://html5.validator.nu/?doc=data%3Atext%2Fhtml%3Bcharset%3Dutf-8%2C%3C!doctype+html%3E%3Ctitle%3E%3C%2Ftitle%3E%3Cp%2520contenteditable%2520oninput%3D%22alert('%3Clol%3E')%22%3E And you’re right about the XHTML compatibility of `\x3C` an sich, but since XHTML doesn’t support `document.write` (or `innerHTML`) anyway I don’t see how that’s relevant. – Mathias Bynens Jun 30 '11 at 10:37
  • 2
    @MathiasBynens—`document.write` is irrelevant, it just happens to be the example. The OP could have used innerHTML, it's the about hiding hiding the `` character sequence from the markup parser, wherever it occurs. It's just that most parsers tolerate it inside a script element when strictly they shouldn't (but HTML parsers are very tolerant). You are correct though that `<\/` suffices in all cases for HTML. – RobG Jun 17 '12 at 11:56
  • 1
    Who writes the web technology specs??, it seems not people who actually use the technologies in question. – Jonathan. Nov 13 '12 at 20:41
  • 3
    I don't think escaping the opening < is necessary.... `document.write(' – Matt Browne Jan 04 '13 at 14:35
  • @MattBrowne It's not just browsers you need to worry about. I got bit by this using PHP's `DOMDocument` to process some HTML that contained some JS that built and inserted an ` – David Harkness Feb 23 '16 at 02:19
  • @MattBrowne - just for completeness sake, if the javascript: label in required in inline scripts in (older) IE if the first script on the page is not JavaScript (e.g. vbscript), then perhaps it is also required on script tags coming after a non-js script – mplungjan Mar 16 '17 at 13:44
  • 40

    Here's another variation I've used when wanting to generate a script tag inline (so it executes immediately) without needing any form of escapes:

    <script>
        var script = document.createElement('script');
        script.src = '/path/to/script.js';
        document.write(script.outerHTML);
    </script>
    

    (Note: contrary to most examples on the net, I'm not setting type="text/javascript" on neither the enclosing tag, nor the generated one: there is no browser not having that as the default, and so it is redundant, but will not hurt either, if you disagree).

    Stoffe
    • 2,744
    • 2
    • 25
    • 24
    • 1
      Good point re: type. The default is defined as "text/javascript" as of HTML5, so it's a useless attribute. http://www.w3.org/html/wg/drafts/html/master/scripting-1.html#attr-script-type – Luke Sep 02 '14 at 22:18
    • 10
      This one is better than the accepted answer because this variation can be actually minified. This 'x3C/script>' will become '' after minification. – Zoltan Kochan Jun 09 '15 at 13:45
    21

    I think is for prevent the browser's HTML parser from interpreting the <script>, and mainly the </script> as the closing tag of the actual script, however I don't think that using document.write is a excellent idea for evaluating script blocks, why don't use the DOM...

    var newScript = document.createElement("script");
    ...
    
    Christian C. Salvadó
    • 807,428
    • 183
    • 922
    • 838
    12

    The </script> inside the Javascript string litteral is interpreted by the HTML parser as a closing tag, causing unexpected behaviour (see example on JSFiddle).

    To avoid this, you can place your javascript between comments (this style of coding was common practice, back when Javascript was poorly supported among browsers). This would work (see example in JSFiddle):

    <script type="text/javascript">
        <!--
        if (jQuery === undefined) {
            document.write('<script type="text/javascript" src="http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></script>');
        }
        // -->
    </script>
    

    ...but to be honest, using document.write is not something I would consider best practice. Why not manipulating the DOM directly?

    <script type="text/javascript">
        <!--
        if (jQuery === undefined) {
            var script = document.createElement('script');
            script.setAttribute('type', 'text/javascript');
            script.setAttribute('src', 'http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js');
            document.body.appendChild(script);
        }
        // -->
    </script>
    
    Mathieu Rodic
    • 6,637
    • 2
    • 43
    • 49
    • 1
      If you want to use pure JS, you will want to still use document.write ;) – Nirav Zaveri Jan 31 '16 at 20:36
    • Sorry, I meant to write - this requires jQuery Library, right? When I used, document.body.append, it threw an error that document.body.append is not a function. – Nirav Zaveri Feb 01 '16 at 11:26
    • 1
      Sorry, my mistake: I wrote `append` instead of `appendChild`. Corrected the answer. Thank you for noticing! – Mathieu Rodic Feb 01 '16 at 13:22
    • 1
      This looks so much more general than splitting up the string manually. E.g. splitting is not feasible if the string is inserted by a template engine. – w1th0utnam3 Jan 25 '17 at 14:37
    9

    The solution Bobince posted works perfectly for me. I wanted to offer an alternative method as well for future visitors:

    if (typeof(jQuery) == 'undefined') {
        (function() {
            var sct = document.createElement('script');
            sct.src = ('https:' == document.location.protocol ? 'https' : 'http') +
              '://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js';
            sct.type = 'text/javascript';
            sct.async = 'true';
            var domel = document.getElementsByTagName('script')[0];
            domel.parentNode.insertBefore(sct, domel);
        })();
    }
    

    In this example, I've included a conditional load for jQuery to demonstrate use case. Hope that's useful for someone!

    Jongosi
    • 2,305
    • 1
    • 28
    • 31