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

Kar*_*lis 1 javascript browser cross-browser

我想模仿这种行为:

<script src="console.log.1.js"></script>
<script>console.log(2)</script>
<script>console.log(3)</script>
Run Code Online (Sandbox Code Playgroud)

注销:

1
2
3
Run Code Online (Sandbox Code Playgroud)

这样做不起作用:

<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>
Run Code Online (Sandbox Code Playgroud)

它注销:

2
3
1
Run Code Online (Sandbox Code Playgroud)

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

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

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

UPDATE

仅供参考,如果有人想知道,以下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>
Run Code Online (Sandbox Code Playgroud)

工作和注销:

"before"
"during"
"after"
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 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>
Run Code Online (Sandbox Code Playgroud)

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

但是添加一个script元素appendChild只是根本不同,它本质上是一个异步操作(你的代码在脚本下载时继续,而script标记中的元素除了这些元素deferasync属性之外的情况不是这样).我不能指出任何一个规范说出原因,但你所看到的行为正是我所期待的.script与标记内联的元素处理有点特殊.

通过比较结果与使用内联script元素的元素,我们可以看到下载是问题 - 至少在Chrome中.

使用外部文件(实时复制 | 实时源):

<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>
Run Code Online (Sandbox Code Playgroud)

结果:

before
after
during

使用内联脚本(实时复制 | 实时源代码  - 请注意,我没有尝试制作这种跨浏览器,它可以在Chrome和Firefox中使用,因为它们支持元素text上的属性script):

<script>
console.log("before");
(function() {
    var s = document.createElement("script");
    s.text = "console.log('during');";
    document.body.appendChild(s);
})();
</script>
<script>
console.log("after");
</script>
Run Code Online (Sandbox Code Playgroud)

输出:

before
during
after