Your scripts do execute synchronously
your code if put together is:
1. create script element
2. set its attribute src
3. set its attribute deferred
4. display done...
this first part stops execution and hands it over to next script
5. script executes and displays Hi
Everything is very much synchronous... In Javascript some code is executed completely until it executes to the last line or hands execution over to internal systems (like XHR or timer).
When one would like to put prepare some parts to execute later on, they prepare it with setTimeout. Even if timeout is shorter than the rest of the code will take that's the time it will execute. After code has finished executing. Example:
// some code
setTimeout(function(){ alert("I'm second alert"); }, 1);
longExecutionTask();
alert("I'm the first alert");
In the above code even if setTimeout is set to execute after 1ms it won't start until the code after it finishes execution which ends with displaying an alert box. The same happens in your case. The first batch of code has to finish executing before anything else can start.
Why you're getting exception (in example 2)
You've added some more code after I've written my answer so here goes some more info.
Adding a script tag will not immediately execute it. Script loading+execution will happen when HTML parser will get to the SCRIPT element you added. It will load it at that point and evaluate/execute its content.
- HTML parser starts parsing your document
HEAD is being parsed and its SCRIPT child tag gets parsed and executed. This execution adds one more element to BODY tag that hasn't been parsed yet.
- Parser moves on to
BODY and parses its content (the newly added SCRIPT tag) which then loads the script and executes its content.
SCRIPT elements get immediately executed only when you they're added after your page has been parsed and is already rendered in browser. In your case that is not the case. The first script executes immediately and the dynamically added one executes when parses gets to it.