开发者社区> 技术小牛人> 正文

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 ,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
JavaScript Window - 浏览器对象模型
浏览器对象模型 (BOM) 使 JavaScript 有能力与浏览器“对话”。 浏览器对象模型 (Browser Object Model) 尚无正式标准。
919 0
VB动态加载纯DLL资源
一、纯DLL资源的制作            打开VC6.0 创建一个基于win32的动态链接库   下一步中,要选择A sinmple Dll project              然后加载资源(注意对于超过256色的位图,VC不能编辑,不过这没关系)           可以加载位图、图标、字符串等,这是加载后的情况      资源添加完毕后,编译。
465 0
JavaScript浏览器对象模型BOM
本文目录 1. 何为BOM 2. BOM常用方法
39 0
Linux下apache服务器安装,sqlite安装,apache启动,关闭,重启,编写cig程序进行测试,浏览器访问cig程序
 1安装ubuntu 14.04 64位操作系统 2安装apache和sqllite以及依赖的sqllite开发库 3配置目录 /etc/apache2 4 html页面目录 var/www/ 5 cgi-bin目录 /usr/lib/cgi-bin 6日志文件:/var/log/apache2 7站点配
2050 0
php_curl.dll libssh2.dll 始终无法加载的原因 及解决办法
在StackOverflow得到最终原因及解决办法 http://stackoverflow.com/questions/16424117/php-unable-to-load-php-curl-dll-extension libeay32.
883 0
悬赏任务源码,了解更多加载方式提升用户体验
悬赏任务源码,了解更多加载方式提升用户体验
18 0
C#:通过NuGet程序包下载CefSharp来加载谷歌浏览器
    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------       首先我讲明一下我要做的,公司有个C# wpf的项目需要我把一个开发好的网页嵌入到客户端当中,由于种种原因,我放弃了ie,转而选择了CefSharp 本篇博客会讲如何安装C...
2333 0
5723
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载