Всё только о JavaScript

document.write

document.write(arg1[, arg2[, arg3[, ...]]]) — метод, выводящий на страницу переданные ему аргументы. Аргументов может быть любое количество, и они могут быть любых типов, при выводе они преобразуются в строки.

Также существует функция document.writeln, которая аналогична document.write, но добавляет в конце своего вывода перевод строки.

Как работает document.write

document.write выводит свои аргументы после того тега script, в котором он был вызван. К примеру код

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    document.write('<h1>Hello, World!</h1>');
</script>
</body>
</html>

равнозначен следующему

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
</script><h1>Hello, World!</h1>
</body>
</html>

Обратите внимание: не после того тега script, в котором записано выражение document.write, а после того, в котором оно было вызвано. Следующий код

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    function hello() {
        document.write('<h1>Hello, World!</h1>');
    }
</script>
<hr>
<script type="text/javascript">
    hello();
</script>
</body>
</html>

выведет

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
</script>
<hr>
<script type="text/javascript">
</script><h1>Hello, World!</h1>
</body>
</html>

а никак не

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
</script><h1>Hello, World!</h1>
<hr>
<script type="text/javascript">
</script>
</body>
</html>

document.write работает только на этапе загрузки страницы, его нельзя вызывать в ответ на какое-нибудь событие. Если document.write вызвать после того, как страница загрузилась, результат во всех браузерах будет примерно одинаков — пустая страница и, возможно, тот текст, который был выведен последним document.write. Поэтому даже не пытайтесь использовать его в ответ на какие-то действия пользователя, только на этапе загрузки страницы.

Вывод скриптов

Как и любое другое содержимое, document.write может выводить и скрипты, которые тоже в свою очередь могут содержать document.write. Но нужно помнить: внедрённые в HTML скрипты не могут содержать внутри себя в явном виде строку </script>. Нужно или разорвать этот тег на части '</sc' + 'ript>', или заменить какой-нибудь символ на escape-последовательность <\x2fscript>. В скриптах, содержащихся во внешних файлах, такие манипуляции не требуются.

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    document.write('<script type="text/javascript">alert(1);<\x2fscript>');       // Выведет окошко alert
</script>
</body>
</html>

Если вложенные скрипты тоже, в свою очередь, содержат document.write, то всё будет выведено последовательно.

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    document.write('Создаём первый скрипт...<br>');
    document.write('<script type="text/javascript">document.write("Первый скрипт<br>");<\x2fscript>');
    document.write('Создаём второй скрипт...<br>');
    document.write('<script type="text/javascript">document.write("Второй скрипт<br>");<\x2fscript>');
    document.write('Закончили.<br>');
</script>
</body>
</html>

Результат на странице будет

Создаём первый скрипт...
Первый скрипт
Создаём второй скрипт...
Второй скрипт
Закончили.

Однако такая последовательность сохраняется до тех пор, пока мы не решим подключить внешние скрипты, выводящие текст на страницу. Создадим, например, файл test1.js с содержимым

document.write('Содержимое test1.js<br>');

И файл test2.js с содержимым

document.write('Содержимое test2.js<br>');

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

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    document.write('Подключаем test1.js<br>');
    document.write('<script type="text/javascript" src="test1.js"><\x2fscript>');
    document.write('Подключаем test2.js<br>');
    document.write('<script type="text/javascript" src="test2.js"><\x2fscript>');
    document.write('Закончили подключать<br>');
</script>
</body>
</html>

В Firefox и Safari выведется ожидаемое

Подключаем test1.js
Содержимое test1.js
Подключаем test2.js
Содержимое test2.js
Закончили подключать

А вот Opera, Chrome и Internet Explorer поведут себя в какой-то мере логично, но не последовательно.

Подключаем test1.js
Подключаем test2.js
Закончили подключать
Содержимое test1.js
Содержимое test2.js

Другими словами, если Firefox и Safari обрабатывают появляющиеся скрипты последовательно, независимо от того, внешние они или внедрёные, то Opera, Chrome и IE выполняют внешние созданные динамически скрипты только после того, как выполнится текущий блок <script>.

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

Разный результат в разных браузерах:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    document.write('Подключаем test1.js<br>');
    document.write('<script type="text/javascript" src="test1.js"><\x2fscript>');
    document.write('Закончили подключать<br>');
</script>
</body>
</html>

Одинаковый результат во всех браузерах:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    document.write('Подключаем test1.js<br>');
    document.write('<script type="text/javascript" src="test1.js"><\x2fscript>');
    document.write('<script type="text/javascript" src="end.js"><\x2fscript>');
</script>
</body>
</html>

Где содержимое end.js:

document.write('Закончили подключать<br>');

Примеры ошибочного использования

Как было сказано выше, document.write выводит текст только во время загрузки страницы. В этом и заключается основная ошибка многих начинающих JavaScript-программистов — они пытаются использовать document.write в ответ на пользовательские события, например, onclick, в результате чего получают пустую страницу.

Запомните, если вы хотите изменить содержимое блока, то нужно найти этот блок в DOM-дереве, например, по его идентификатору, и изменить у него свойство innerHTML.

document.getElementById('content').innerHTML = 'Новое содержимое';

Область применения

Области применения у document.write две: создать новый документ с нуля и сгенерировать динамический контент в том самом месте, где находится родительский элемент script. Всё остальное вариации этих двух случаев.

Генерация нового документа

Если нужно открыть новое окно или создать новый фрейм, содержимое которых не загружается с какого-то урла, а должно генерироваться динамически, то самый простой способ — это написать содержимое нового документа с помощью document.write.

var w = window.open();
w.document.open();  // Открываем документ для записи
w.document.writeln('<!DOCTYPE html>');
w.document.write('<html><head></head><body>Это динамическое окно.</body></html>');
w.document.close(); // Заканчиваем формирование документа

Обратите внимание на вызов метода close, пока он не вызван, браузер считает, что документ ещё не до конца загружен, и не убирает индикатор загрузки.

Вывод динамического содержимого на этапе загрузки

Под таким сложным заголовком скрывается простая вещь. Предположим мы хотим выводить на странице текущий день недели. Тогда в то место, где он должен находиться, нужно вставить следующий код.

Сегодня <script type="text/javascript">document.write(['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'][new Date().getDay()])</script>.

Несмотря на предрассудки по отношению к document.write, это самый простой способ, в отличие от DOM-методов, и в подобных случаях он более чем уместен.

Информеры для внешних сайтов

Ещё одна область применения для document.write — предоставление кодов сторонним сайтам для вывода различных виджетов, информеров, банеров, контекстных объявлений и прочих подобных вещей. Смысл здесь в том, чтобы предоставить неискушённому пользователю код, который он сможет без лишних движений поставить в то место, где должен появляться соответствующий блок. Тогда пользователю выдаётся простой код в виде тега script и, возможно, инициализации каких-то параметров.

<script type="text/javascript" src="http://oursite.ru/informer.js"></script>

А в этот скрипт уже выдаётся код, который создаёт нужный html-код.

document.write('Я информер');