是使用document.write唯一可能的方式来跨浏览器跨域同步加载脚本?

时间:2012-03-07 17:43:39

标签: javascript browser cross-browser

我想模仿这种行为:

<script src="console.log.1.js"></script>
<script>console.log(2)</script>
<script>console.log(3)</script>

注销:

1
2
3

这样做不起作用:

<script>
var x = document.createElement("script");
x.src = "console.log.1.js";
x.async = false;
x.defer = false;
document.body.appendChild(x);
console.log("2");
console.log("3");
</script>

注销:

2
3
1

我到目前为止找到的唯一方法是实现它:

<script>
document.write("<scrip" + "t src='console.log.1.js'></scrip" + "t>");
</script>
<script>
console.log("2");
console.log("3");
</script>

这是否是在所有浏览器中强制同步加载外部脚本的唯一方法?为什么不设置async = false,defer = false工作?

更新

仅供参考,如果有人想知道,以下document.write开始有效(在Chrome中):

<script>
  // http://jsbin.com/avatiw logs "during"
  document.write('<scrip' + 't>console.log("before");document.write("<scrip" + "t src=\\"http://jsbin.com/avatiw\\"></scrip" + "t>");</scrip' + 't>');
  document.write('<scrip' + 't>console.log("after");</scrip' + 't>');
</script>

工作并注销:

"before"
"during"
"after"

2 个答案:

答案 0 :(得分:5)

是的,这是在页面解析期间强制脚本加载的唯一方法。或者至少,我愿意相信的唯一方式是跨浏览器。

如果您的脚本是这样的,我可以看到您的想法:

<script>
var x = document.createElement("script");
x.src = "console.log.1.js";
x.async = false;
x.defer = false;
document.body.appendChild(x);
</script>
<script><!-- note the new script element -->
console.log("2");
console.log("3");
</script>

...因为理论上,当解析器命中script元素时,它会挂起所有内容(因为可能有document.write个语句)并调用JavaScript层。因此,您可能会认为,在script的末尾添加body元素会将其插入到两者之间。

但是通过script添加appendChild元素只是根本不同,它本质上是一个异步操作(在下载脚本时代码会继续,{{1}不是这种情况标记中的元素禁止scriptdefer属性。我不能指出任何一个规范说出原因,但你所看到的行为正是我所期待的。对标记内联的async元素的处理有点特殊。

我们可以通过将结果与使用内联内容的script元素进行比较来确定下载是问题 - 至少在Chrome中是这样。

使用外部文件(live copy | live source):

script

结果:

before
after
during

使用内嵌脚本(live copy | live source - 请注意,我没有尝试制作此跨浏览器,因为它们支持<script> console.log("before"); (function() { var s = document.createElement("script"); s.src = "http://jsbin.com/avatiw"; // Logs the word "during" document.body.appendChild(s); })(); </script> <script> console.log("after"); </script> 属性,因此可以在Chrome和Firefox中使用在text元素上:

script

输出:

before
during
after

答案 1 :(得分:0)

我实际上发现使用LazyLoad插件非常适合这种用例,即

if (typeof jQuery === 'undefined')
    LazyLoad.js('//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js', function() { 
        initialize(); 
    });
else
    initialize();