Зачем разделять тег <script> при его написании с помощью document.write ()?

Почему некоторые сайты (или рекламодатели, которые предоставляют клиентам код javascript) используют метод разделения тегов <script> и / или </script> в рамках вызовов document.write()?

Я заметил, что Amazon тоже делает то же самое, например:

<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>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
274
0
129 068
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я думаю, это для предотвращения интерпретации HTML-парсером браузера <script> и, в основном, </script> как закрывающий тег фактического скрипта, однако я не думаю, что использование document.write - отличная идея для оценки скрипта. блоки, почему бы не использовать DOM ...

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

Это необходимо для того, чтобы синтаксический анализатор не закрывал скрипт-блок преждевременно ...

roenving 25.10.2008 12:53
Ответ принят как подходящий

</script> должен быть разбит, потому что в противном случае он преждевременно завершит включающий блок <script></script>. На самом деле он должен быть разделен между < и /, потому что блок сценария предполагается (согласно SGML) как оканчивается любой последовательностью открытого концевого тега (ETAGO) (например, </):

Although the STYLE and SCRIPT elements use CDATA for their data model, for these elements, CDATA must be handled differently by user agents. Markup and entities must be treated as raw text and passed to the application as is. The first occurrence of the character sequence "</" (end-tag open delimiter) is treated as terminating the end of the element's content. In valid documents, this would be the end tag for the element.

Однако на практике браузеры заканчивают синтаксический анализ блока сценария CDATA только по фактическому закрывающему тегу </script>.

В XHTML нет такой специальной обработки для блоков сценария, поэтому любой символ < (или &) внутри них должен быть &escaped;, как и в любом другом элементе. Однако тогда браузеры, которые разбирают XHTML как HTML старой школы, запутаются. Есть обходные пути, связанные с блоками CDATA, но проще всего избегать использования этих символов без экранирования. Лучшим способом написать элемент сценария из сценария, который работает с любым типом синтаксического анализатора, был бы:

<script type = "text/javascript">
    document.write('\x3Cscript type = "text/javascript" src = "foo.js">\x3C/script>');
</script>
/ - допустимая escape-последовательность для /, так почему бы просто не использовать ее вместо тех строковых буквальных escape-последовательностей для <? Например. document.write('<script src=foo.js></script>');. Кроме того, </script> - не единственная последовательность символов, которая может закрывать элемент <script>. Дополнительная информация здесь: mathiasbynens.be/notes/etago
Mathias Bynens 29.06.2011 14:58

@Mathias: </script> в этом случае подойдет, но он будет работать только в HTML; в XHTML без дополнительной упаковки разделов CDATA это все равно ошибка правильности. Также вы можете использовать \x3C во встроенных атрибутах обработчика событий, где < также будет недопустимым как в HTML, так и в XHTML, поэтому он имеет более широкое применение: если бы я выбрал один, легко автоматизированный способ экранирования чувствительных символов в строковых литералах JS для всех контекстов , это тот, который я бы выбрал.

bobince 29.06.2011 23:39

В HTML < можно использовать во встроенных атрибутах обработчика событий. html5.validator.nu/… И вы правы насчет XHTML-совместимости \x3C и так далее, но поскольку XHTML не поддерживает document.write (или innerHTML) в любом случае, я не понимаю, насколько это актуально.

Mathias Bynens 30.06.2011 14:37

@ MathiasBynens - document.write не имеет значения, это просто пример. OP мог бы использовать innerHTML, это касается сокрытия последовательности символов </ от синтаксического анализатора разметки, где бы это ни происходило. Просто большинство парсеров допускают это внутри элемента скрипта, хотя строго не должны (но парсеры HTML очень терпимы). Вы правы, хотя </ подходит для HTML во всех случаях.

RobG 17.06.2012 15:56

Кто пишет спецификации веб-технологий? Кажется, это не люди, которые на самом деле используют эти технологии.

Jonathan. 14.11.2012 00:41

Я не думаю, что нужно избегать открытия <.... document.write('<script src = "foo.js">\x3C/script>') кажется достаточным для всех браузеров, начиная с IE6. (Я пропустил атрибут type, потому что он не требуется ни в HTML5, ни в каком-либо браузере).

Matt Browne 04.01.2013 18:35

@MattBrowne Вам нужно беспокоиться не только о браузерах. Я получил немного от этого, используя PHP DOMDocument для обработки некоторого HTML, содержащего JS, который построил и вставил <iframe>. Синтаксический анализатор увидел открывающий тег и создал узел DOM, но тег не был завершен, и синтаксический анализатор начал экранировать пробелы в остальной части JS-кода с помощью %20!

David Harkness 23.02.2016 05:19

@MattBrowne - просто для полноты картины, если метка javascript: требуется во встроенных скриптах в (более старом) IE, если первый скрипт на странице не является JavaScript (например, vbscript), то, возможно, это также требуется для тегов скрипта, следующих после не-js скрипт

mplungjan 16.03.2017 16:44

Вот еще один вариант, который я использовал, когда хотел сгенерировать встроенный тег скрипта (чтобы он выполнялся немедленно) без необходимости в какой-либо форме экранирования:

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

(Примечание: вопреки большинству примеров в сети, я не устанавливаю type = "text/javascript" ни на включающий тег, ни на сгенерированный: нет браузера, не имеющего этого по умолчанию, и поэтому он избыточен, но не повредит , если вы не согласны).

Хороший момент re: type. По умолчанию в HTML5 определено как «текст / javascript», так что это бесполезный атрибут. w3.org/html/wg/drafts/html/master/…

Luke 03.09.2014 02:18

Этот лучше, чем принятый ответ, потому что этот вариант можно фактически минимизировать. После минификации этот 'x3C / script>' станет '</script>'.

Zoltan Kochan 09.06.2015 16:45

Решение, опубликованное Бобинсом, отлично подходит для меня. Я хотел предложить и альтернативный метод для будущих посетителей:

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);
    })();
}

В этом примере я включил условную загрузку для jQuery, чтобы продемонстрировать вариант использования. Надеюсь, это кому-то пригодится!

нет необходимости определять протокол - URI без протокола работает нормально (//foo.com/bar.js и т. д.)

dmp 15.07.2016 15:35

также нет необходимости устанавливать асинхронный режим. он установлен для всех динамически создаваемых тегов скрипта.

Noishe 10.06.2017 23:18

Спас меня! При использовании document.write (<script>) мой сайт показывал пустой экран. Это сработало.

Tomas Gonzalez 27.06.2017 21:19

@dmp, кроме случаев, когда запускается из файловой системы, где протоколом будет file: //

mplungjan 06.02.2018 09:04

</script> внутри строки Javascript интерпретируется анализатором HTML как закрывающий тег, вызывая неожиданное поведение (см. пример на JSFiddle).

Чтобы избежать этого, вы можете поместить свой javascript между комментариями (этот стиль кодирования был обычной практикой, когда Javascript плохо поддерживался браузерами). Это будет работать (см. пример в 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>

... но, честно говоря, использование document.write - не лучшая практика. Почему бы не манипулировать DOM напрямую?

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

Если вы хотите использовать чистый JS, вы все равно захотите использовать document.write;)

Nirav Zaveri 31.01.2016 23:36

Извините, я хотел написать - для этого нужна библиотека jQuery, верно? Когда я использовал document.body.append, он выдавал ошибку, что document.body.append не является функцией.

Nirav Zaveri 01.02.2016 14:26

Извините, моя ошибка: я написал append вместо appendChild. Подправил ответ. Спасибо, что обратили внимание!

Mathieu Rodic 01.02.2016 16:22

Это выглядит гораздо более общим, чем ручное разделение строки. Например. разделение невозможно, если строка вставлена ​​механизмом шаблонов.

w1th0utnam3 25.01.2017 17:37

Другие вопросы по теме