Когда браузер выполняет Javascript? Как движется курсор выполнения? - PullRequest
53 голосов
/ 26 февраля 2010

Мне было интересно, есть ли доступные ресурсы, которые описывают, как курсор браузера выполняет Javascript.

Я знаю, что он загружает и выполняет теги при загрузке страницы, и что вы можете прикреплять функции к различным событиям окна,но все становится неясным, когда, например, я получаю удаленную страницу через AJAX и помещаю ее содержимое в div.

Если эта удаленная страница должна загружать библиотеки сценариев, такие как <script src="anotherscript.js" />, когдаЗагружается «anotherscript.js» и выполняется его содержимое?

Что произойдет, если я добавлю «anotherscript.js» на свою текущую страницу, а затем загружу некоторый удаленный контент, в котором есть дубликаты этого сценария?Перезаписывает ли он оригинал?Что если в исходном "anotherscript.js" есть переменная, значение которой я изменил, а затем я перезагружаю этот файл ... я теряю исходное значение или игнорируется второе включение этого сценария?

Если я загружаю какой-то процедурный Javascript через AJAX, когда он выполняется?Сразу после того, как я mydiv.innerHTML(remoteContent)?Или это выполнено до этого?

Ответы [ 2 ]

53 голосов
/ 26 февраля 2010

Ответ зависит от того, где находится тег script и как вы его добавили:

  1. Теги скрипта, встроенные в вашу разметку, выполняются синхронно с обработкой этой разметки в браузере (кроме случаев, см. # 2), и поэтому, если - например - эти теги ссылаются на внешние файлы, они имеют тенденцию замедляться обработка страницы. (Это значит, что браузер может обрабатывать document.write операторов, которые изменяют разметку, которую они обрабатывают.)

  2. Теги сценариев с атрибутом defer могут в некоторых браузерах выполняться только после полной визуализации DOM. Естественно, они не могут использовать document.write. (Точно так же есть атрибут async, который делает сценарий асинхронным, но я мало что знаю об этом или о том, насколько хорошо он поддерживается; подробности .)

  3. Теги сценария в содержимом, которое вы назначаете элементам после загрузки DOM (через innerHTML и аналогичные), вообще не выполняются, за исключением того, что вы используете библиотеку, такую ​​как jQuery или Prototype, чтобы сделать это за вас. (За одним исключением, на которое указал Энди Э. В IE, если у них есть атрибут defer, он их выполнит. Не работает в других браузерах.)

  4. Если вы добавите фактический элемент script в документ с помощью Element#appendChild, браузер начнет загрузку этого сценария немедленно и выполнит его, как только загрузка будет завершена. Сценарии, добавленные таким образом, не выполняются синхронно или не обязательно по порядку. Сначала добавление <script type="text/javascript" src="MyFct.js"></script>, а затем добавление <script type="text/javascript">myFunction();</script> может выполнять встроенный (второй) один перед удаленным (первым). Если это произойдет и MyFct.js объявит myFunction(), он не будет определен, когда мы попытаемся использовать его со встроенным скриптом. Если вам нужно, чтобы все было сделано по порядку, вы можете узнать, когда удаленный скрипт был загружен, наблюдая за событиями load и readyStateChange в добавляемом элементе script (load - это событие в большинстве браузеров, readyStateChange в некоторых версиях IE, и в некоторых браузерах это возможно, поэтому вам приходится обрабатывать несколько уведомлений для одного и того же скрипта).

  5. Сценарий внутри обработчиков событий для атрибутов (<a href='#' onclick='myNiftyJavaScript();'>), а не для тега сценария, выполняется, когда происходит соответствующее событие.


Я работал на своей Реальной Работе, и вдруг мой задний мозг сказал: «Вы знаете, вам сказали , что они не будут выполнены, если вы назначите их innerHTML, но лично вы проверил?» И у меня не было, поэтому я сделал - FWIW:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Script Test Page</title>
<style type='text/css'>
body {
    font-family: sans-serif;
}
</style>
<script type='text/javascript'>
function addScript()
{
    var str, div;

    div = document.getElementById('target');
    str = "Content added<" + "script type='text/javascript'>alert('hi there')<" + "/" + "script>";
    alert("About to add:" + str);
    div.innerHTML = str;
    alert("Done adding script");
}
</script>
</head>
<body><div>
<input type='button' value='Go' onclick='addScript();'>
<div id='target'></div>
</div></body>
</html>

Предупреждение от скрипта не появляется в IE7, FF3.6 или Chrome4 (я не удосужился проверить других, я должен работать :-)). Принимая во внимание, что если вы добавляете элементы, как показано здесь , скрипт выполняется.

3 голосов
/ 26 февраля 2010

Если вы просто вставите блок HTML, содержащий теги сценария, в вашу DOM с помощью «innerHTML», теги сценария не будут выполняться вообще. Когда вы загружаете что-то вроде jQuery, код в этой библиотеке явно обрабатывает поиск и выполнение сценариев.

Это не совсем точно, но вы можете думать об обработке тега <script> так, как если бы все содержимое тега (т. Е. Тело скрипта) было выполнено с eval(). Если скрипт объявляет глобальные (оконные) переменные, тогда старые значения перезаписываются.

Теги скрипта обрабатываются в порядке их появления. Конечно, код внутри блоков скрипта может быть настроен так, что при первоначальном выполнении он откладывает обработку real на более поздний срок. Много кода установки / инициализации jQuery сделает это.

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