动态加载JS文件的执行

3

我知道JS是单线程的,并且同步执行。因此,当我添加一个文件到浏览器头部标签时,该文件会在遇到它时立即执行。然后它会去下一个脚本标签并执行那个文件。我的问题是,当我动态地将一个js文件添加到HTML头部标签中时,浏览器如何执行该文件?

它是否像加载文件时一样立即执行文件,无论当前执行位置在哪里。或者我们可以控制该文件的执行方式吗?


请发布您用于追加JS文件的代码。 - Fabrizio Calderan
我实际上并没有进行任何JS文件的动态加载。我只是想知道是否有一种方法可以控制我们加载的文件何时执行。 - shaunshd
我认为这取决于您注入脚本标记的方式。在浏览器上尝试一些代码,打开Firebug,在consolenetwork面板中记录一些调试信息并查看发生了什么。 - pomeh
4个回答

3
当JavaScript文件被动态加载时会发生什么(非常简化,没有检查):
  1. 文件被加载;
  2. 如果有函数调用,例如doSomething()(function(){...})(),则代码将被执行(当然必须有定义);
  3. 如果只有函数定义,则在函数调用之前不会发生任何事情。
请参见此示例:加载了3个文件,2个立即执行,1个等待超时。
编辑:
脚本标签可以放置在页面的任何位置。实际上,如果未使用onload事件,则最好将其放置在页面末尾(雅虎网站性能优化建议)。
使用HTML5,JavaScript具有Web Worker技术,详情请参见:MDN MSDN Wikipedia

3

脚本加载后,将尽快执行。也就是说,如果其他JavaScript函数正在执行(如clickhandler或其他),该函数将被允许先完成 - 但这是可以预见的,因为在浏览器中JavaScript通常在单个线程中执行。

您无法控制脚本加载的部分,但可以使用此模式-受JSONP的启发:

插入脚本:

(function () {
    var module = {
        init: function () {
            /* ... */
        }
    }

    ready(module);  // hook into "parent script"
}());

主页面上的脚本:

function ready(o) {
    // call init in loaded whenever you are ready for it...
    setTimeout(function () { o.init(); }, 1000);
}

这里关键是您页面上定义的 ready 函数,并在您动态插入的脚本中调用。脚本不会立即开始执行,而是只会告诉父页面它已加载完成,然后父页面可以随时回调插入脚本的 init 函数以启动执行。


你能详细说明如何调用动态插入的脚本吗?例如,如果我使用onload()调用一个脚本,比如:<body onload="displayResult()">,该脚本会将另一个脚本插入到head中。那么我该如何调用已插入脚本中的函数呢?因为我不知道它何时加载完成。 - Rahul Iyer
诀窍在于你要反过来做。因此,在你的主脚本中,你定义一个名为resultReady的全局方法,然后在由displayResult()插入的脚本底部调用resultReady函数。 - AHM

1

考虑一种实现方法:

var js=document.createElement('script')
js.setAttribute("type","text/javascript")
js.setAttribute("src", filename)
document.getElementsByTagName("head")[0].appendChild(js); 
// ^ However this technique has been pointed to be not so trusworthy (Read the link in the comment by Pomeh)

回答你的问题:

浏览器如何执行该文件?

脚本一旦添加到DOM中,就会立即执行。

是不是文件在加载时无论当前执行位置在哪里都会被执行?

是的。

还是说我们可以控制文件的执行方式?

最好是附加一个onload事件处理程序,而不是使用恶意技巧。


我相信问题是关于动态添加文件时代码的流程如何,而不是如何动态添加。 - Amit
这并不是那么简单 http://paulirish.com/2011/surefire-dom-element-insertion/ - pomeh
@Starx 很好。在你第一次编辑后,我也更新了我的评论,因为你没有回答问题 :) - pomeh

-3

这里有一些代码,你可以尝试用它来得到你的问题的答案。

<script>
var s = document.createElement('script'), f = 1;
s.src="http://code.jquery.com/jquery-1.7.2.js";
document.head.appendChild(s)
s.onload = function(){
  console.log(2);
  f = 0    
}
while(f){
    console.log(1);
}
</script>

这段代码理想情况下应该在脚本加载时打印出2,但是如果你注意到了,这从来没有发生过。
注意:这会让你的浏览器崩溃!

while(f) - 这似乎是致命的部分。 - Bakudan
确实如此。我正在使用它来展示JS的执行方式。由于浏览器被卡在while循环中,它永远不会调用onload事件。 - Amit
我真的不喜欢while部分。 - Starx
1
-1 这并没有回答问题,也没有展示任何东西。它只是恶意代码... - AHM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接