20

Never met this problem, and don't know why. The only explanation is a scope issue.

In the same page, I have 2 sections of JS :

...
 <script type="text/javascript">
    go();
  </script>

  <script type="text/javascript">
    function go()
    { alert('');  }
  </script>
...

This will show an error : go is not defined

where

...
     <script type="text/javascript">
        go();

        function go()
        { alert('');  }
      </script>
    ...

is working (obviously).

Does <script> tag creates a scope of JS ? help ?

1
  • 7
    by using script tags you should first define the function and then call it. Commented Jun 10, 2012 at 13:05

4 Answers 4

27

This isn't a scope issue. If you define a function (in the global scope) in one script element, then you can use it in another.

However, script elements are parsed and executed as they are encountered.

Hoisting won't work across script elements. A function defined in a later script element won't be available during the initial run of an earlier script element.

You either need to swap the order of your script elements, or delay the function call until after the script that defines it has run (e.g. by attaching it to an onload event handler).

<script>
    function go() {
        alert('');  
    }
</script>
<script>
    go();
</script>

or

<script>
    window.addEventListener("load", function () { 
        go();
    }, false);
</script>
<script>
    function go() {
        alert('');  
    }
</script>
Sign up to request clarification or add additional context in comments.

1 Comment

@floorish — Whoops. Thanks for the catch!
8

The html parser stops to execute your script before moving to next elements. So the next script element is not executed until the first one is executed.

This is comparable to:

<script>
document.getElementById("hello") //null because the html parser hasn't met the div yet.
</script>
<div id="hello"></div>

Comments

2

The other cause of this as an apparent error is if the first script block has a syntax error and is rejected in its entirety, but the second block runs on and misses its buddy code.

Comments

0

As it's been said already, order matters. For what it's worth, I saw this issue with an experiment (not production!) where I had something like this:

<head>
    <script src="/path/one.js" defer>
</head>
<body>
    <script>
        methodInOneJs();
    </script>
</body>

And the browser complained with a ReferenceError, even though methodInOneJs() was defined in one.js. This because of the defer attribute in the script that loads it. One might think that putting defer in the inline script as well would solve the issue, but according to MDN:

Warning: This attribute must not be used if the src attribute is absent (i.e. for inline scripts), in this case it would have no effect.

One quick solution (aside from removing defer altogether) was to use the onload event (again, not production, where I'd just use src):

<head>
    <script src="/path/one.js" defer>
</head>
<body onload="run();">
    <script>
        function run()
        {
            methodInOneJs();
        }
    </script>
</body>

This is because with defer:

the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded.

Emphasis on "before firing DOMContentLoaded". See also how to load scripts last.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.