script标记的加载方式(多浏览器测试)

简介:
< DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd>

Script Call, 与XMLHttpRequest、IFrame Call,是Ajax开发中最常见的三种数据传输器。在传输方式上,XMLHttpRequest可以通过参数设置使用异步还是同步; IFrame Call 一定是异步的,那Script Call是怎样呢?在不同的浏览器上是否遵循一样的规则呢?

本文设计一个简单的测试用例,看看静态<script>载入与动态<script>载入的区别,以及两者在主流浏览器(FireFox1.5|Opera8.5|IE6)上的表现异同。

测试如下:
//test.js:
function printV(msg) {
    document.write("<br>" + msg + " : v = ");
    try {
        document.write(v);
    } catch (e) {
        document.write("null");
    }
}

<!-- test1.html-->
<script type="text/javascript" src="test.js"></script>
<script>
printV("after static script loaded");
</script>
test1.html在三个浏览器中的表现一模一样,输入都是:

after static script loaded : v = 100
所以可以推知,静态<script>加载脚本在浏览器解析的过程中是同步的。
document.write("<script>"),用document.write的形式写入一个<script>标签是一种常用的动态载入脚本的方法,很多JavaScript类库都使用这样的方式来模拟php或者python的 "require" 或者 "import" 语句,达到动态并且可控制加载脚本的目的。

首先,测试 document.write语句与printV函数调用在同一个<script>块的情况:

<!-- test2.html-->
<script>
document.write('<script type="text/javascript" src=""></script>');
printV("after documentWriteScript");
</script>
各个浏览器对test2.html的执行结果有了区别: FireFox与IE6都是马上打印出v=null,结果如下:

after documentWriteScript loaded : v = null
只有Opera能够在一会延迟后打印出v的值。接下来稍微修改一下代码,将document.write语句和printV函数调用放在两个不同的<script>块中:
<!-- test3.html-->
<script>
document.write('<script type="text/javascript" src="></script>');
</script>
<script>
printV("after documentWriteScript");
</script>
结果让我略有些吃惊,test3.html在各个浏览器中的表现再度相同,与静态<script>载入效果一样。那么可以推断出浏览器解析脚本的一些处理逻辑:

FireFox1.5 和 IE6 解析同一个<script>块中代码的时候,如果发现动态<script>载入,那么是异步执行的。但在解析下一个<script>块(或者其他html标签)之前,会保证当前<script>块执行完成,也就是说,FireFox1.5和IE6逐个解析<script>标签的过程是同步的。
Opera8.5 则是保证每句脚本都解析并执行完成,再执行下一语句。即使是动态载入脚本,也要加载完成后才继续执行。
head.appendChild([script node])

document.write 在整个DOM已经被渲染完成以后就不适用了,比如在window.onload事件方法中执行document.write的话,将覆写掉已有的内容。除了document.write写入的方式,还有一种常见的动态载入脚本的方法,那就是利用DOM为<head>(或<body>)创建一个script element。测试代码如下:

<script>
<!--test4.html-->
var script = document.createElement("script");
script.src = "test.jsp";
document.getElementsByTagName_r("head")[0].appendChild(script);
printV("after documentAppendScript");
</script>
同样还有不同<script>块的版本
<script>
<!--test5.html-->
var script = document.createElement("script");
script.src = "test.jsp";
document.getElementsByTagName_r("head")[0].appendChild(script);
</script>
<script>
printV("after documentAppendScript");
</script>
可预测的,Firefox1.5和IE6在test4 vs. test2 和test5 vs.test3中结果对应相同。Opera8.5则一直都能有效打印出v的值。

总结

通过对三个浏览器的简单测试,可以发现,FireFox1.5与IE6在不同测试中表现一致,Opera8.5则在不同测试中自身表现始终一致。

从整个html中看,每个<script>是同步的
所以我们常常看到,一些类库使用一个简单的js脚本,作为类库加载器,例如ActiveWidget的grid.js脚本源码:
function $import(path){
    var i, base, src = "grid.js", scripts = document.getElementsByTagName_r("script");
    for (i=0; i<scripts.length; i++){if (scripts[i].src.match(src)){ base = scripts[i].src.replace(src, "");break;}}
document.write("<" + "script src="" + base + path + ""></" + "script>");
}
原理就是首先获取自己的src,解析出url路径,然后调用document.write加载相同url下的指定类库。因为加载器和其后的程序调用一定是在不同的<script>块,所以不会出现对象未定义的脚本错误。
在关联的JavaScript代码中动态<script>载入是异步的(Opera为同步)
利用动态<script>载入脚本可以避免XMLHttpRequest的跨域限制,所以常常用来和JSON配套使用,JSONP 新名词也由此而生。JSONP(JSON with Padding)的原理简单说就是:将回调的JS语句或函数名作为script url中的参数提交,服务端返回的脚本数据的最后,则执行参数传递来的脚本。
Yahoo! Web Services提供JSON apiUsing JSON with Yahoo! Web Services,以及del.icio.us|利用<script>加载用户书签的例子 Javascript Objects 都是JSONP形式调用的实现。因为JSONP需要客户端与服务端的配合,所以带来避免跨域限制的长处同时,灵活性不如XMLHttpRequest。

另外,FireFox1.5为<script>提供了onload 注册事件,IE6提供了onreadystatechange注册事件。Opera8.5 则两者都不支持,但由于Opera8.5对<script>永远是同步执行方式,所以也没有支持的必要。

虽然浏览器间没有达成完全统一,但对于 JSONP 形式的处理,浏览器的表现是一致的。<script>标签与JavaScript的关系,加上Script Call比IFrame Call更利于直接获取数据,可以预见,Ajax应用中Script Call 会有更广泛应用以作为XmlHttpRequest的补充。

本文转自 netcorner 博客园博客,原文链接:http://www.cnblogs.com/netcorner/archive/2008/01/19/2912230.html ,如需转载请自行联系原作者

相关文章
|
机器学习/深度学习 PyTorch 算法框架/工具
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
这篇文章介绍了如何使用PyTorch框架,结合CIFAR-10数据集,通过定义神经网络、损失函数和优化器,进行模型的训练和测试。
790 2
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
|
运维 Prometheus 监控
如何在测试环境中保持操作系统、浏览器版本和服务器配置的稳定性和一致性?
如何在测试环境中保持操作系统、浏览器版本和服务器配置的稳定性和一致性?
|
缓存 监控 前端开发
在资源加载优化中,如何利用浏览器缓存提升性能?
通过以上这些方法,可以有效地利用浏览器缓存来提升资源加载的性能,减少网络请求次数,提高用户体验和应用的响应速度。同时,需要根据具体的应用场景和资源特点进行灵活调整和优化,以达到最佳的效果。此外,随着技术的不断发展和变化,还需要持续关注和学习新的缓存优化方法和策略。
648 159
|
数据采集 消息中间件 JavaScript
浏览器渲染揭秘:从加载到显示的全过程;浏览器工作原理与详细流程
了解浏览器工作原理与流程,能有效帮助前端开发与性能优化。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
2107 1
|
Web App开发 定位技术 iOS开发
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
1301 1
|
测试技术 Python
自动化测试项目学习笔记(三):Unittest加载测试用例的四种方法
本文介绍了使用Python的unittest框架来加载测试用例的四种方法,包括通过测试用例类、模块、路径和逐条加载测试用例。
485 0
自动化测试项目学习笔记(三):Unittest加载测试用例的四种方法
|
Web App开发 缓存 Linux
高效Selenium测试技巧:轻松控制已开启的浏览器
【10月更文挑战第13天】在进行Selenium测试时,通常会启动新浏览器实例,但有时需要控制已开启的浏览器,以节省时间并更真实地模拟用户行为。这可通过设置Chrome为可远程控制并使用`Remote WebDriver`连接实现。需在启动Chrome时添加`--remote-debugging-port`参数,并通过Python脚本中的`webdriver.Remote`连接至指定端口。此外,还可利用会话ID(Session ID)重新连接浏览器,提高测试灵活性。需要注意浏览器版本兼容性及元素定位稳定性等问题,确保测试准确性和一致性。
1366 1
|
安全 Oracle Java
edge浏览器加载java插件
edge浏览器加载java插件
1318 1
|
机器学习/深度学习 人工智能 并行计算
StableDiffusion-01本地服务器部署服务 10分钟上手 底显存 中等显存机器 加载模型测试效果 附带安装指令 多显卡 2070Super 8GB*2
StableDiffusion-01本地服务器部署服务 10分钟上手 底显存 中等显存机器 加载模型测试效果 附带安装指令 多显卡 2070Super 8GB*2
425 0

热门文章

最新文章

下一篇
开通oss服务