views:

354

answers:

4

JavaScript programs consist of statements and function declarations. When a JavaScript program is executed, these two steps occur:

  1. the code is scanned for function declarations, and every func. declaration is "executed" (by creating a function object) and a named reference to that function is created (so that this function can be called from within a statement)

  2. the statements are executed (evaluated) sequentially (as they appear in the code)

Because of that, this works just fine:

<script>
    foo();
    function foo() {
        return;
    }
</script>

Although the "foo" function is called before it is declared, it works because the function declaration is evaluated before the statement.

However, this does not work:

<script>
    foo();
</script>
<script>
    function foo() {
        return;
    }
</script>

An ReferenceError will be thrown ("foo is not defined"). This leads to the conclusion that every SCRIPT element inside the HTML code of the web-site represents a separate JavaScript program and every time the HTML parser encounters a SCRIPT element, it executes the program inside that element (and then once the program is executed, the parser moves on to the HTML code that follows the SCRIPT element).

Then again, this does work:

<script>
    function foo() {
        return;
    }
</script>
<script>
    foo();
</script>

My understanding here is that the Global object (which serves as the Variable object in the global execution context) exists (and remains) at all times, so the first JavaScript program will create the function object and make a reference for it, and then the second JavaScript program will use that reference to call the function. Therefore, all JavaScript programs (within a single web-page) "use" the same Global object, and all changes done to the Global object by one JavaScript program can be observed by all JavaScript programs that run subsequently.

Now, note this...

<script>
    // assuming that foo is not defined
    foo();
    alert(1);
</script>

In the above case, the alert call will not execute, since the "foo()" statement throws a ReferenceError (which breaks the whole JavaScript program) and therefore, all subsequent statements do not execute.

However, in this case...

<script>
    // assuming that foo is not defined
    foo();
</script>
<script>
    alert(1);
</script>

Now, the alert call does get executed. The first JavaScript program throws a ReferenceError (and as a consequence breaks), but the second JavaScript program runs normally. Of course, the browser will report the error (although it did execute subsequent JavaScript programs, after the error occurred).

Now, my conclusions are:

  • every SCRIPT element within the HTML code of the web-page represents a separate JavaScript program. These programs execute immediately as the HTML parser encounters them.
  • all JavaScript programs within the same web-page "use" the same Global object. That Global object exists at all times (from the moment the web-page is fetched up until the web-page is destroyed). JavaScript programs may manipulate the Global object, and all changes done to the Global object by one JavaScript program are observed in all subsequent JavaScript programs.
  • if one JavaScript program breaks (by having an error thrown), that does not prevent subsequent JavaScript programs to run.

Please fact-check this post and tell me if I got something wrong.

Also, I have not found resources that explain the behaviors mentioned in this post, and I assume that the browser makers must have published such resources somewhere, so if you know about them, please provide the links to them.

UPDATE!

OK, I am going to (try to) answer my own question here :) I got a response (via e-mail) from Dmitry A. Soshnikov (he runs a blog about JavaScript at http://www.dmitrysoshnikov.com/ ).

His take on this issue is this: Each SCRIPT block contains global code. Executing each SCRIPT block creates a new execution context. So, each SCRIPT block has its own execution context, but all those execution contexts share the same Global object.

Therefore, SCRIPT blocks could be seen as different "sub-programs" with the same shared state.

Furthermore, the ECMAScript spec (3rd edition) states (chapter 10): "Global code is source text that is treated as an ECMAScript Program."

+5  A: 

They are separate programs, but they modify a shared global object.

Mike Stay
+10  A: 

Function hoisting — the process that evaluates function statements before the rest of the function — is part of the ECMAScript standard IIRC (I can't find a reference right now, but I recall seeing discussions of EMCAScript that mention it). The evaluation of script tags is part of the HTML standard. It does not specify that they are "separate programs" in so many words, but it does say that the script elements are evaluated in the order they appear in the document. That is why functions in later script tags aren't hoisted: The script hasn't been evaluated yet. That also explains why one script stopping doesn't cut off subsequent scripts: When the current script stops evaluating, the next one starts.

Chuck
Link explaning HOISTING. http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
Rajat
+7  A: 

Dmitry Soshnikov has answered your question. Every <script> element is executed as a Program, as defined by the ECMAScript specification. There is one global object that each Program within a single page uses. And that's really it.

Tim Down
Yes, I agree with that nomenclature. However, I am reluctant to accept an answer yet. I would like to get an answer that provides a link to a resource (as in documentation) published by a browser maker which describes how a SCRIPT block is handled by the browser. I assume that such a resource possibly would clarify this issue.
Šime Vidas
A: 

Another way to think about this is pseudo local vs global scope. Every SCRIPT declaration has a local scope to it's current methods/functions, as well as access to the current (previously declared) global scope. Whenever a method/function is defined in a SCRIPT block, it is then added to the global scope and becomes accessible by the SCRIPT blocks after it.

Also, here's a further reference from W3C on script declaration/handling/modification:

The dynamic modification of a document may be modeled as follows:

  1. All SCRIPT elements are evaluated in order as the document is loaded.
  2. All script constructs within a given SCRIPT element that generate SGML CDATA are evaluated. Their combined generated text is inserted in the document in place of the SCRIPT element.
  3. The generated CDATA is re-evaluated.

This is another good resource on script/function evaluation/declaration.

bryan.taylor