一、应用场景:

有时候我们需要动态创建script标签实现脚本的按需加载,我们会为script标签绑定onload或者onreadystatechange事件,用于检测动态脚本是否加载并执行完毕,在事件处理程序中引用动态脚本创建的变量。

二、问题描述:

如果我们动态创建script标签并绑定事件处理程序后,立即移除script标签,那么事件处理程序是否会执行?如果能执行,那么能否正常引用动态脚本创建的变量?

三、看如下程序:

function inviteFriends() {
var self = this; if ($("#onlineserviceMailToFriend").size() > 0) {
showMail();
} else {
var jsUrl = "http://images.139cm.com/mpost2014/js/mpost/onlineservice/m2012.mpost.onlineservice.view.mailtofriend.js?v=1.0"; // 动态创建script标签加载脚本
M139.core.utilCreateScriptTag({
id : "onlineserviceMailToFriend",
src : jsUrl,
charset : "utf-8"
}, showMail);
} // 异步请求脚本之后马上移除script标签
$("#onlineserviceMailToFriend").remove(); // script标签的onload或onreadystatechange事件处理程序
function showMail() {
if (!self.mailToFriend) {
// IE系列会报错找不到对象:M2012.Mpost.OnlineService.View.MailToFirend
// chrome浏览器可正常运行
self.mailToFriend = new M2012.Mpost.OnlineService.View.MailToFirend({
model : self.model
});
}
self.mailToFriend.render();
}
}
/**
*动态加载script标签
*@param {Object} options 配置
*@param {Stirng} options.id script标签的id ;
*@param {Stirng} options.src JS文件地址(完整路径);
*@param {Stirng} options.charset 给script标签加charset属性
*@param {Function} callback 加载完成的回调
*@example
*M139.core.utilCreateScriptTag(
{
id:"examplejs",
src:"http://images.139cm.com/m2012/richmail/js/example.js",
charset:"utf-8"
},
function(){
alert("文件加载完毕");
}
*);
*/
function utilCreateScriptTag(options, callback) {
var This = this;
if (callback) {
var _callback = callback;
var callback = function() {
_callback.call(This);
}
}
var scriptId = options.id;
var dataHref = this.getScriptPath(options.src);
var charset = options.charset;
var isReady = false;
var head = document.getElementsByTagName("head")[0];
var objScript = scriptId && document.getElementById(scriptId);
//是否移出脚本DOM(非IE9时处理)
var isRemoveScriptDom = !document.all && true || false, browserVersion = ["msie 10.0", "msie 9.0", "chrome", "firefox"], i = 0, bvLenght = browserVersion.length - 1, currVersion = window.navigator.userAgent.toLowerCase() || "";
//IE9、chrome、firefox时处理
while (i <= bvLenght) {
isRemoveScriptDom = currVersion.indexOf(browserVersion[i]) > -1 && true || false;
if (isRemoveScriptDom) {
break;
}
i++;
}
browserVersion = null;
try {
if (objScript && isRemoveScriptDom) {
objScript.src = "";
objScript.parentNode.removeChild(objScript);
objScript = null;
}
} catch (e) {
}
if (objScript != null) {
if (dataHref.indexOf("?") == -1)
dataHref += "?";
dataHref += "&" + Math.random();
objScript.src = dataHref;
var dataScript = objScript;
} else {
var dataScript = document.createElement("script");
if (scriptId) {
dataScript.id = scriptId;
}
if (charset) {
dataScript.charset = charset;
}
try {
if (dataHref.indexOf("?") == -1) {
dataHref = M139.Text.Url.makeUrl(dataHref, {
sid : top.$App.getSid()
});
}
} catch (e) {
}
dataScript.src = dataHref;
dataScript.defer = true;
dataScript.type = "text/javascript";
head.appendChild(dataScript);
}
if (document.all) {
dataScript.onreadystatechange = function() {
if (dataScript.readyState == "loaded" || dataScript.readyState == "complete") {
isReady = true;
if (callback)
callback();
}
}
} else {
dataScript.onload = function() {
isReady = true;
if (callback)
callback();
}
dataScript.onerror = function() {
isReady = true;
if (callback)
callback();
}
}
}

四、结论:

由于函数utilCreateScriptTag是通过属性赋值的方式注入事件处理程序,而移除脚本调用的是jQuery的remove方法,dom虽然移除但事件依然存在于内存,所以当浏览器加载脚本并执行完毕,事件处理程序依然会被调用,这一点IE浏览器与标准浏览器表现一致,但是当试图在事件处理程序中引用动态脚本创建的变量时,IE系列无一例外的报错,而标准浏览器却可以正常引用。

移除script标签引起的兼容性问题的更多相关文章

  1. JavaScript之<script>标签简介

    向html页面中插入JavaScrpt的主要方法,就是使用<script>元素,下面是Html 4.01为<script>定义的6个属性. 1.async:可选表示应该立即下载 ...

  2. script标签

    script 元素既可以包含脚本语句,也可以通过 src 属性指向外部脚本文件.默认情况下script标签的会阻止文档渲染,相关脚本会立即下载并执行. 属性 在HTML5中script主要有以下几个属 ...

  3. script标签加载顺序(defer & async)

    script 拥有的属性 async:可选,表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本.只对外部脚本文件有效. charset:可选.表示通过 src 属性指 ...

  4. [转]Script标签和脚本执行顺序

    Script标签和脚本执行顺序 这里详细聊聊和script标签相关的脚本执行顺序. Script标签的默认行为 几个首要特性: script标签(不带defer或async属性)的会阻止文档渲染.相关 ...

  5. [译]我们应该在HTML文档中何处放script标签

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  6. javaScript中的小细节-script标签中的预解析

    首先介绍预解析,虽然预解析字面意思很好理解,但是却是出坑出的最多的地方,也是bug经常会有的地方,利用好预解析的特性可以解决很多问题,并且提高代码的质量及数量,浏览器在解析代码前会把变量的声明和函数( ...

  7. script标签中defer和async属性的区别

    这篇文章来源于JS高级程序设计第三版中关于script标签的介绍,结合查阅的资料写下的学习笔记. 向html页面中插入javascript代码的主要方法就是通过script标签.其中包括两种形式,第一 ...

  8. HTML 5 <script> 标签

    HTML 4.01 与 HTML 5 之间的差异 async 属性是 HTML 5 中的新属性. 在 HTML 5 中,不再支持 HTML 4.01 中的一些属性. 提示和注释 注释:脚本按照如下方式 ...

  9. script标签里的defer属性

    入职新公司,看代码的时候注意到有的script标签中有一个defer属性,查了一下.在这里分享出来. 需要注意的有三点,其中前两点是在错误中分辨出来的: 错误来源:http://www.w3schoo ...

随机推荐

  1. 下载azure website的code

    1.登陆kudu直接下载. http://www.concurrency.com/blog/use-azure-kudu-debug-azure-websites/ 2.FTP链接拷贝(可以忽略) 3 ...

  2. memcache 未授权访问漏洞

    memcache是一套常用的key-value缓存系统,由于它本身没有权限控制模块,所以开放在外网的memcache服务很容易被攻击者扫描发现,通过命令交互可直接读取memcache中的敏感信息. 修 ...

  3. python创建shape

    import shapefile import json import os #shapefile="polygon.shp"; #jsonfile="社区网格.json ...

  4. nuget服务器搭建

    本文章主要介绍如何将本地dll打包成为一个Nuget包,并如何发布到自己的nuget服务器,示例代码下载.章节如下 1. 本地dll如何打包,以及版本的更新 2. 在linux上搭建nuget.ser ...

  5. bzoj3261: 最大异或和 (可持久化trie树)

    题目链接 题解 看到异或和最大就应该想到01 trie树 我们记\(S_i\)为前i项的异或和 那么我们的目的是最大化\(S_n\)^\(x\)^\(S_{j-1}\) \((l <= j &l ...

  6. 计算机插U盘没用了

    今天遇到一个神奇的状况,我想把台机上面的文件通过U盘拷贝到我的笔记本上.文件拷到U盘上没问题,然后把U盘插到笔记本上,一点反应都没有.我想了下,这U盘肯定没坏.然后我笔记本又是新买没多久,一直爱护有加 ...

  7. 关于zipfile解压出现的字符编码问题

    使用zipfile解压文件时,出现了中文乱码问题,具体解决方法有两个,直接上代码吧. def deco_zip(path, file_path): os.mkdir(file_path) # 方式一 ...

  8. Oracle KEEP的用法

    [摘录自] http://blog.itpub.net/12932950/viewspace-687036/ http://flyfx.iteye.com/blog/1994993 聚合函数MIN, ...

  9. 获取数组中多个相加等于0的一组数字 javascript

    //获取数组中两个相加等于0的一对数字,比如[ [ -10, 10 ], [ -5, 5 ] ] var arr=[-5,10,1,-10,3,4,5,9] //对数组进行排序 arr.sort(fu ...

  10. 最小生成树的kruskal、prim算法

    kruskal算法和prim算法 都说 kruskal是加边法,prim是加点法 这篇解释也不错:这篇 1.kruskal算法 因为是加边法,所以这个方法比较合适稀疏图.要码这个需要先懂并查集.因为我 ...