When does the browser execute Javascript? How does the execution cursor move?
Solution 1
The answer varies depending on where the script tag is and how you've added it:
Script tags inline with your markup are executed synchronously with the browser's processing of that markup (except, see #2), and so if -- for instance -- those tags reference external files, they tend to slow down the processing of the page. (This is so the browser can handle
document.write
statements, which change the markup they're processing.)Script tags with the
defer
attribute may, on some browsers, not be executed until after the DOM has been fully rendered. Naturally these can't usedocument.write
. (Similarly there's anasync
attribute that makes the script asynchronous, but I don't know much about it or how well it's supported; details.)Script tags in content you assign to elements after DOM load (via
innerHTML
and similar) are not executed at all, barring your use of a library like jQuery or Prototype to do it for you. (With one exception pointed out by Andy E: On IE, if they have adefer
attribute, it will execute them. Doesn't work in other browsers.)If you append an actual
script
element to the document viaElement#appendChild
, the browser begins downloading that script immediately and will execute it as soon as the download is finished. Scripts added this way are not executed synchronously or necessarily in order. First appending a<script type="text/javascript" src="MyFct.js"></script>
, and then appending<script type="text/javascript">myFunction();</script>
may well execute the inline (second) one before the remote (first) one. If that happens andMyFct.js
declaresmyFunction()
, it will not be defined when we try to use it with the inline script. If you need things done in order, you can tell when a remote script has been loaded by watching theload
andreadyStateChange
events on thescript
element you add (load
is the event on most browsers,readyStateChange
on some versions of IE, and some browsers do both, so you have to handle multiple notifications for the same script).Script inside event handlers on attributes (
<a href='#' onclick='myNiftyJavaScript();'>
) rather than in a script tag is executed when the relevant event occurs.
I was working away at my Real Job and suddenly my hindbrain said "You know, you've been told they won't be executed if you assign them to innerHTML
, but have you personally checked?" And I hadn't, so I did -- 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>
The alert from the script doesn't appear on IE7, FF3.6, or Chrome4 (I haven't bothered to check others, I'm meant to be working :-) ). Whereas if you append elements as shown here, the script gets executed.
Solution 2
If you just stuff a block of HTML containing script tags into your DOM with "innerHTML", the script tags won't be executed at all. When you load stuff with something like jQuery, code in that library explicitly handles finding and executing the scripts.
It's not precisely accurate, but you can basically think of the processing of a <script>
tag as if the whole contents of the tag (i.e., the script body) were executed with eval()
. If the script declares global (window) variables, then old values are overwritten.
Script tags are processed in the order that they appear. Of course the code inside the script blocks may be set up so that what it does upon initial execution is to defer the real processing until later. Lots of jQuery setup/initialization code will do that.
aw crud
Updated on September 05, 2020Comments
-
aw crud over 3 years
I was wondering if there are any available resources that describe how a browser's cursor executes Javascript.
I know it loads and executes tags when a page loads, and that you can attach functions to various window events, but where things get fuzzy is when, for instance, I retrieve a remote page via AJAX and put its contents into a div.
If that remote page has got to load script libraries such as
<script src="anotherscript.js" />
, when is "anotherscript.js" being loaded and its contents are being executed?What happens if I included "anotherscript.js" on my current page, and then I load some remote content which has a duplicate include of this script? Does it overwrite the original one? What if the original "anotherscript.js" has a var in it whose value I altered, and then I reload that file... do I lose the original value or is the second inclusion of this script ignored?
If I load some procedural Javascript via AJAX, when is it executed? Immediately after I do
mydiv.innerHTML(remoteContent)
? Or is it executed before that? -
Adrian Schmidt about 14 yearsI was told that innerHTML will parse and execute JavaScript. That's why you should be careful around innerHTML :) But maybe that's only true for the content of a tag, not for a .js-file linked in src= ?
-
Pointy about 14 yearsWell try it :-) I know that jQuery explicitly does different stuff when it detects that a string argument to
html()
doesn't have any script tags in it - specifically, it just usesinnerHTML()
. -
T.J. Crowder about 14 years@Adrian: Re "...I was told that innerHTML will parse and execute JavaScript. That's why you should be careful around innerHTML..." Well, you never want to assign user-provided content directly to an element via
innerHTML
if that's what you're being careful of, but I'm not aware of a browser that executesscript
tags (inline or referencing an external file) when you do. -
aw crud about 14 years@T.J. Crowder: Wow... thanks for all the details and the test as well. I'm pretty sure when I used jQuery.html(...) it was executing the scripts within immediately, but I didn't realize that was jQuery and not default javascript behavior. I guess I need to look into the jQuery code because I'm pretty sure the API guide didn't mention this.
-
Andy E about 14 years@T.J.: Internet Explorer will if you scratch it in just the right spot behind it's ear: stackoverflow.com/questions/1891947/…
-
Andy E about 14 years@T.J.: add the
defer
attribute to theinnerHTML =
example you tried and try it again in IE :-) -
T.J. Crowder about 14 years@Andy: !! Cool, thanks! I Did Not Know That. :-) Looks like it's just IE, though. Still, good to know.
-
T.J. Crowder about 14 years@RI: No worries, stuff I've picked up along the way. Surprising about the jQuery docs not talking about it, but I'm not immediately seeing it either. (docs.jquery.com/Attributes/html) Prototype's docs do.
-
Olga over 12 yearsI was wondering, you say "Please note however that non inline scripts added this way are not executed synchronously" could you may provide any reference for this subject? Say I am trying to load a script from a server which is down (really busy or else) would it affect the page?
-
T.J. Crowder over 12 years@Olga: It won't prevent other code on your page from running if that's what you mean. When you append a
script
element referencing a remote script, your code continues to run while the browser goes and fetches it. If the browser can't fetch it, it'll have about the same impact as (say) an image it can't fetch. -
Olga over 12 yearsThat is very good news thanks, the problem is that I was looking hard for some kind of proof link for this fact like a specification or else
-
T.J. Crowder over 12 years@Olga: I don't know of any reference that actually says it in so many words, although it may well be hidden deep in the treacle that is the
script
section of the HTML5 specification. :-) But I know it's true, and cross-browser consistent.