javascript - Varför dela upp <script>-taggen när man skriver den med document.write()?


Varför använder vissa webbplatser (eller annonsörer som ger klienter javascript-kod) en teknik där <script> och/eller </script> taggar delas upp inom document.write()-anrop?

Jag lade märke till att Amazon gör detta också, till exempel:

<script type='text/javascript'>
  if (typeof window['jQuery'] == 'undefined') document.write('<scr'+'ipt type="text/javascript" src="http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></sc'+'ript>');
</script>

Svar #1

</script> måste delas upp eftersom det annars skulle avsluta det omgivande <script></script>-blocket för tidigt. Egentligen borde det delas mellan < och /, eftersom ett scriptblock enligt SGML ska avslutas med vilken som helst end-tag open (ETAGO)-sekvens (d.v.s. </):

Även om STYLE- och SCRIPT-elementen använder CDATA för sin datamodell, måste CDATA hanteras på ett annat sätt av användaragenter för dessa element. Märkning och enheter måste behandlas som rå text och skickas till applikationen som de är. Det första förekomsten av teckensekvensen "</" (sluttag-öppningsavgränsare) behandlas som att den avslutar elementets innehåll. I giltiga dokument skulle detta vara sluttaggen för elementet.

Men i praktiken slutar webbläsare bara analysera ett CDATA-skriptblock vid en faktisk </script>-stängningstag.

I XHTML finns det ingen särskild hantering för skriptblock, så alla < (eller &) tecken inom dem måste &escaped; precis som i vilket annat element som helst. Men då blir webbläsare som tolkar XHTML som gammaldags HTML förvirrade. Det finns lösningar som involverar CDATA-block, men det är enklast att helt enkelt undvika att använda dessa tecken oescaped. Ett bättre sätt att skriva ett skriptelement från skript som fungerar på båda typer av parser skulle vara:

<script type="text/javascript">
    document.write('\x3Cscript type="text/javascript" src="foo.js">\x3C/script>');
</script>

Svar #2

Här är en annan variation jag har använt när jag vill generera en script-tagg inline (så att den körs omedelbart) utan att behöva någon form av escape:

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

(Obs: till skillnad från de flesta exempel på nätet sätter jag inte type="text/javascript" varken på den omslutande taggen eller den genererade: det finns ingen webbläsare som inte har det som standard, och därför är det överflödigt, men det skadar inte heller, om du inte håller med).

Svar #3

Jag tror att det är för att förhindra webbläsarens HTML-tolk från att tolka <script>, och främst </script> som sluttaggen för det faktiska skriptet, men jag tror inte att det är en utmärkt idé att använda document.write för att utvärdera skriptblock, varför inte använda DOM...

var newScript = document.createElement("script");
...

Svar #4

Koden </script> inuti Javascript-strängliteralet tolkas av HTML-parsern som en stängningstag, vilket orsakar oväntat beteende (se exempel på JSFiddle).

För att undvika detta kan du placera din javascript mellan kommentarer (denna stil av kodning var vanligt förekommande, när Javascript hade dåligt stöd bland webbläsare). Detta skulle fungera (se exempel i 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>

...men ärligt talat, att använda document.write är inte något jag skulle betrakta som bästa praxis. Varför inte manipulera DOM direkt?

<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>

Relaterade artiklar