Метод
Можно вставить строку, которая явно сломает остальную страницу:
Или можно поиграть в русскую рулетку:
Оказывается, тот факт, что текст вставляется сразу после тега
Данный код выведет ошибку о том, что переменная jQuery не объявлена.
С другой стороны:
А этот код выполнится без ошибок, потому что второй тег
Дальше становится все любопытнее. Представим, что есть такой код:
А в файле
Данный код выведет в консоль следующее:
Из этого примера видно, что весь код из первого тега
Следует помнить. что этот способ вставки контента работает только непосредственно во время загрузки документа. Что будет, если вызвать
Существует ли нормальный повод применять
Я о таком не слышал. По всей видимости, он используется в баннерокрутилках, потому что позволяет показать отслеживающую картинку вместо AJAX-запроса, если пользователь заходит на сайт через Netscape 2. В современном же мире он особо ни для чего не нужен.
Правда, иногда встречаются замечательные инструменты, которые незаметно оборачивают передаваемый вами HTML в вызовы
Можно ли вызвать
Ага!
Нет, 20 раз.
Ага.
Google Chrome, несомненно, более совершенный браузер — там можно аж 21 раз.
Разработчики Firefox первыми исправили баг, потенциально позволявший уронить браузер, а разработчики Webkit скопировали их решение. Ходят слухи, что в IE тоже есть некий предел, но он еще ниже.
(Код взят из тикета)
Какие еще глупости можно натворить с
Да какие угодно!
Например, можно сделать синхронный AJAX-запрос и вставить его результат непосредственно в тело страницы:
Отправка запроса заблокирует загрузку основной страницы, и содержимое ответа будет вставлено так, как если бы оно изначально располагалось на загружаемой странице. В данном случае вместо URL передана пустая строка, поэтому загружаться будет та же самая страница, а она, в свою очередь, снова начнет загружать сама себя, и так до бесконечности*.
* Под «до бесконечности» подразумевается 20 раз. Или 21. Или еще меньше, если вы в IE.
В общем, можно развлекаться по-разному.
В текущей спецификации этого нет (хотя было в прошлых версиях), но можно передавать в
А вот это действительно хороший вопрос!
Примечание переводчика:
Любопытно, что только первый вызов
document.write
— один из самых странных методов. Он вставляет HTML-код на страницу сразу после себя. Точнее говоря, сразу после тега <script>
, внутри которого он расположен. И только в том случае, если документ еще не был загружен полностью. А если был? Тогда страница очищается и заменяется на, что было указано.Можно вставить строку, которая явно сломает остальную страницу:
document.write('<plaintext>')
Или можно поиграть в русскую рулетку:
if (Math.random() > 0.9)
document.write('<!--')
Оказывается, тот факт, что текст вставляется сразу после тега
<script>
— это важно. Например:<script>
document.write('<script src="jquery.js"></' + 'script>');
alert(jQuery.guid)
</script>
Данный код выведет ошибку о том, что переменная jQuery не объявлена.
С другой стороны:
<script>
document.write('<script src="jquery.js"></' + 'script>');
</script>
<script>
alert(jQuery.guid)
</script>
А этот код выполнится без ошибок, потому что второй тег
<script>
не начнет исполняться до тех пор, пока не будет полностью обработан скрипт, подгруженный из первого тега.Дальше становится все любопытнее. Представим, что есть такой код:
<script>
console.log('a');
document.write('<script src="printC.js"></' + 'script>');
console.log('b');
</script>
<script>
console.log('d');
</script>
А в файле
printC.js
содержится следующее:console.log('c')
Данный код выведет в консоль следующее:
a
b
c
d
Из этого примера видно, что весь код из первого тега
<script>
после document.write
был выполнен сразу же, а вот второй тег начал исполняться только после того, как завершил свою работу printC.js
.Следует помнить. что этот способ вставки контента работает только непосредственно во время загрузки документа. Что будет, если вызвать
document.write
после того, как он уже загружен? Было бы логично выдать ошибку, или не делать ничего. Вместо этого вся существующая страница стирается, а на ее место выводится переданная строка:setTimeout(function(){
document.write("Oops");
})
Существует ли нормальный повод применять document.write
?
Я о таком не слышал. По всей видимости, он используется в баннерокрутилках, потому что позволяет показать отслеживающую картинку вместо AJAX-запроса, если пользователь заходит на сайт через Netscape 2. В современном же мире он особо ни для чего не нужен.
Правда, иногда встречаются замечательные инструменты, которые незаметно оборачивают передаваемый вами HTML в вызовы
document.write
.Можно ли вызвать document.write
внутри document.write
?
Ага!
Типа, бесконечно много раз?
Нет, 20 раз.
Серьезно? Двадцать?
Ага.
Google Chrome, несомненно, более совершенный браузер — там можно аж 21 раз.
Они что, независимо друг от друга до этого додумались?
Разработчики Firefox первыми исправили баг, потенциально позволявший уронить браузер, а разработчики Webkit скопировали их решение. Ходят слухи, что в IE тоже есть некий предел, но он еще ниже.
Можно ли сломать браузер еще быстрее?
<div id="uniqid">
<script language="JavaScript" type="text/JavaScript">
document.write(">"+document.getElementById('uniqid').innerHTML+"<");
</script>
</div>
(Код взят из тикета)
Какие еще глупости можно натворить с document.write
?
Да какие угодно!
Например, можно сделать синхронный AJAX-запрос и вставить его результат непосредственно в тело страницы:
x = new XMLHttpRequest()
x.open('GET', "", false)
x.send()
document.write(x.responseText);
Отправка запроса заблокирует загрузку основной страницы, и содержимое ответа будет вставлено так, как если бы оно изначально располагалось на загружаемой странице. В данном случае вместо URL передана пустая строка, поэтому загружаться будет та же самая страница, а она, в свою очередь, снова начнет загружать сама себя, и так до бесконечности*.
* Под «до бесконечности» подразумевается 20 раз. Или 21. Или еще меньше, если вы в IE.
В общем, можно развлекаться по-разному.
Что-нибудь еще?
В текущей спецификации этого нет (хотя было в прошлых версиях), но можно передавать в
document.write
несколько параметров, например:document.write("П", "Р", "Е", "В", "Е", "Д");
Если метод бесполезен, зачем я про него вообще читаю?
А вот это действительно хороший вопрос!
Примечание переводчика:
Любопытно, что только первый вызов
document.write
после загрузки страницы очищает ее содержимое. Последующие вызовы дописывают текст после первого.Поделиться с друзьями
schroeder
позвольте ламерский вопрос:
а что значит «когда страница загружена»? Как определяется, что страница загружена?
Vindicar
Я полагаю, после отработки события onLoad?
impwx
Если не ошибаюсь, страница считается загруженной, когда браузер получил ее код от сервера целиком и построил по нему DOM. Пользователь может отследить этот момент, как правильно сказал Vindicar, по событию
onLoad
, или с помощью более удобного синтаксиса у jQuery.heilage
То, что вы описали — это DOMContentLoaded, событие Load срабатывает при полной обработке всех ресурсов страницы. Однако, в таких ненормальных условиях, как наличие document.write непосредственно в script-теге, возможно существует и какое-то иное поведение.
vermilion1
artyfarty
полезно еще знать, что есть document.close(), который по-хорошему стоит вызывать после document.write, иначе некоторые браузеры будут показывать крутилку «загрузки».
yarkov
Если я правильно понял, то document.close(); актуально только при создании дочерних окон и выполнении document.write в контексте нового окна. Так?
artyfarty
В моём случае это наблюдалось с src-less iframe (тобишь да, дочерним окном), но я без понятия, ограничивается ли явление только такими сценариями.
Zenitchik
Оригинальная статья какого года? У меня первая ассоциация: "школьник 21 века и кассетный плеер". Я так стар? Уже выросло поколение, не заставшее эпоху, когда половина сайтов работала на это хреновине?
mike114
Половина энтерпрайза все еще использует document.write, некоторые даже в относительно новых продуктах. Все зависит от того, какой ответ нагуглился и заработал первым у «талантливого» offshore разработчика.
Pakos
Я застал сайт, делавший document.write("<br>"); по числу нужных br'ов. Прошли годы. но я до сих пор не понимаю смысла так делать (в попавшем в руки этом коде просто заменил их на <br> ибо короче, а модемы бывали и на 2400).
olen
> Существует ли нормальный повод применять document.write?
> Я о таком не слышал.
А как же что-то типа этого?
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js"></script>
<script>window.jQuery || document.write('<script src=«js/jquery-2.0.0.min.js»>\x3C/script>')</script>
gearbox
Поговаривают что некоторые программисты пользуют document.createElement('script') — врут наверное.
helarqjsc
По вашей же ссылке лучший ответ:
И следующий ответ советует использовать document.write.
gearbox
А зачем вам это делать synchronously? Какая объективная причина может быть для этого?
sumanai
Чуть ниже могут быть скрипты, зависящие от jQuery, и они сломаются.
gearbox
если сторонний скрипт или легаси — то да, может быть, но в своем коде — то проверяться надо и предохраняться. Зависимостей может не быть по многим причинам.
sumanai
А вы не используете сторонние скрипты и легаси код? Я счастлив за вас.
А в реальном мире и первого и второго навалом, поэтому лучше гарантировать загрузку нужных зависимостей вовремя, нежели чем переписывать тонны скриптов в расчёте на внезапную их пропажу.
gearbox
Использую, зачем вы из меня плюшевого мишку делаете? Дискуссия развернулась с вот этой фразы — "Существует ли нормальный повод применять document.write?". ПОВОД! Не нужда.
sumanai
> Использую, зачем вы из меня плюшевого мишку делаете?
Извиняюсь за немного резкую фразу.
> ПОВОД! Не нужда.
Как- то не отделяю данные понятия. Нужда даёт повод.
gearbox
Принято )
Ну как же? "А как бы нам тут приспособится к этой гребаной либе, которая использует :"№%%:? Да, придется делать document.write." Это нужда.
"А как бы нам тут document.write поиспользовать. Очень хочется, есть где?" Это поиск повода.
Так вот поводов использовать document.write — нет, язык развился, DOM развился, есть нормальные инструменты, закопайте стюардессу.
sumanai
> Так вот поводов использовать document.write — нет
Так же выше повод- синхронная вставка зависимостей, такой стиль имеет право на жизнь.
fireSparrow
>> * Под «до бесконечности» подразумевается 20 раз.
Автор статьи, видимо, раньше в рекламе работал?
adasoft
Применял document.write() именно на этапе загрузки страницы, в зависимости от UserAgent. А далее уже подгружаемый фрейворк разобрал «вписанную» структуру по своим правилам. И всё в одном html файле, без внешних зависимостей и т.п. Помоему довольно удобно.
izyk
wnd=window.open('...');
wnd.document.open('....');
wnd.document.write('....');
LynXzp
«Существует ли нормальный повод применять document.write?» Как-то делал фан-сайт игры основной функциональностью которого было показывать логи. Т.е. информация однотипна, уникальной информации мало, и большую часть составляет статистика вычисленная на основе базовой информации, подсвеченные интересные моменты и т.п. Сначала были static html таблички по мегабайту и больше, но т.к. предполагалось что их должно быть много и храниться должны на сервере чуть ли не вечность переделал html в: и все. А подгружаемый скрипт уже с помощью document.write рисовал всю страницу полностью. В итоге вместо >1Мб html, я получил 100b html + 100kb js (который кэшируется) — неимоверная экономия места на сервере, экономия трафика, и страницы стали загружаться моментально*.
*Под «моментально» имеется в виду время загрузки было меньше времени реакции человека.
gro
Вообще, не совсем «пока страница не загружена».
Когда вызовы идут в основном потоке загрузки, то пишется в этот поток.
Но, например:
setTimeout(function () {
document.write(4);
}, 0);
Если страница будет долго грузится и таймер сработает раньше, он грохнет текущий документ ещё до его загрузки.
GEMOzloBIN
Много раз сталкивался с примерами document.write и до сих пор не понимаю почему всегда когда вставляется скрипт он разбит на части
Но ведь и
будет работать точно также.
Это эстетство или есть определенные подводные камни которые обходят таким образом?
ookami_kb
Перестраховка, по большей части: http://stackoverflow.com/a/236106/1037345
Zenitchik
Закрывающий тег script может быть распознан браузером как конец скрипта. А вот вариант
Валиден повсюду.
Zenitchik
del
saaadel
на сколько я помню, document.write не закрывает документ, и потому дописывает после первого стирания. Сам браузер закрывает документ когда построит DOM, и вызов document.write просто открывает новый документ
попробуйте следующий пример:
document.write(1); document.write(2);
document.close(); document.write(3);
На экране будет только — 3
n1sh
Mobify.js — тыц
unchqua
Не поэтому ли все закладки Geektimes у меня крутятся бесконечно? И даже Escape не останавливает, потому что нажатия перехватываются яндексовой метрикой. Только крестиком остановить можно.
grompe
У меня есть пример использования document.write() в юзерскрипте, в котором нужно полностью заменить страницу своей, с более мощной функциональностью.