//writDoc.js
document.open();
document.write("<script src='config.js'></script><h1>Out with the old - in with the new!</h1>");
document.close();
//html
<!DOCTYPE html>
<html>
<head>
<script src="writeDoc.js"></script>
<script>
console.log(window.config);
</script>
</head>
<body>
<p>Some original document content.</p>
</body>
</html>
啊,那纯粹是因为下载的异步性
如果用 script.text 就没这问题了
至于为什么 document.write 可以,那是因为浏览器会选择下载完再继续解析 HTML
因为你创建的新script加载是异步的,这个新下载也并不会阻塞浏览器往下执行。
可以往全局挂一个config.js加载成功的标志,然后在第二个script中检测这个标志。
猜一下应该是这样的。
浏览器开始解释代码:
发现script1,执行script1(丢了个config.js到head里)
发现script2,执行script2
解释完毕
...
config.js加载成功,执行config.js
因为异步啊
执行第一段时主线程并不等待加载完成,而是执行完后立刻执行第二段
因为前面加载到head时文件未下载执行,而进行了下一个代码片段,异步问题。
现代浏览器支持了对script的
async``和defer`属性的支持,提高浏览器对HTML页面的解析速度和渲染呈现的速度。这2个属性只对设置了scr属性的外部脚本有效,对内联脚本(没有设置src属性的script)无效。没有设置
async或defer属性的脚本按其在html中出现的顺序阻塞式的执行-也就是浏览器会暂停对html页面元素的解析,等script脚本执行完毕后才能继续解析,在解析完成后触发DOMContentLoaded事件。设置有
async/defer属性的script不会阻塞对HTML标签的解析,HTML标签的解析继续进行;设置了async的script将会并发异步的去下载对应的外部脚本文件(可能从本地缓存中获取),下载完成后,通过事件通知机制通知浏览器可以执行进程,事件调度器会调度执行脚本,按下载完成的时间的先后顺序,依次执行。defer的script将会并发异步的去下载对应的外部脚本文件(可能从本地缓存中获取),下载完成后不会马上执行,要等到HTML解析完成后,按脚本出现的顺序依次执行,这个过程中多个脚本之间是顺序执行。async和defer同时指定的情况下,以defer的方式处理script的执行<script>脚本执行是在html解析过程中发生的,只有在在脚本执行了document.write操作时,页面解析器将会解析其中的html内容如果有脚本并马上执行脚本~~
而script脚本有2种类型:
parser-inserted scripts我们经常遇到的出现在HTML中以<script>方式出现,我们姑且称之为解析型脚本script-inserted scripts通过JS代码动态添加的script脚本,动态型脚本,不涉及页面标签的解析这2种类型的script脚本,在
async方式的处理方式有些差异动态型脚本在插入到DOM中后,即使马上从DOM中删除,也不影响脚本的存在:
A: 如果没有设置async属性并设置src属性,那么JS解析器就其当做async=true处理,此脚本将异步加载处理;
B: 如果没有设置src属性,那么无论是否设置async属性,通过为其text属性设置脚本代码的方法,那么动态添加的脚本被马上执行-可以认为是当前脚本一部分(实际不是,作用域不同);这个也是jquer的ajax加载执行外部JS脚本的方式。
c: 如果设置src属性并设置async=false,那么次动态脚本将被同步化处理,但是其执行时机不是暂停当前脚本的执行,而是等当前页面的解析工作完成后。多个async=false脚本按其插入的次序顺序执行。