移除script标签引起的兼容性问题
一、应用场景:
有时候我们需要动态创建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标签引起的兼容性问题的更多相关文章
- JavaScript之<script>标签简介
向html页面中插入JavaScrpt的主要方法,就是使用<script>元素,下面是Html 4.01为<script>定义的6个属性. 1.async:可选表示应该立即下载 ...
- script标签
script 元素既可以包含脚本语句,也可以通过 src 属性指向外部脚本文件.默认情况下script标签的会阻止文档渲染,相关脚本会立即下载并执行. 属性 在HTML5中script主要有以下几个属 ...
- script标签加载顺序(defer & async)
script 拥有的属性 async:可选,表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本.只对外部脚本文件有效. charset:可选.表示通过 src 属性指 ...
- [转]Script标签和脚本执行顺序
Script标签和脚本执行顺序 这里详细聊聊和script标签相关的脚本执行顺序. Script标签的默认行为 几个首要特性: script标签(不带defer或async属性)的会阻止文档渲染.相关 ...
- [译]我们应该在HTML文档中何处放script标签
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- javaScript中的小细节-script标签中的预解析
首先介绍预解析,虽然预解析字面意思很好理解,但是却是出坑出的最多的地方,也是bug经常会有的地方,利用好预解析的特性可以解决很多问题,并且提高代码的质量及数量,浏览器在解析代码前会把变量的声明和函数( ...
- script标签中defer和async属性的区别
这篇文章来源于JS高级程序设计第三版中关于script标签的介绍,结合查阅的资料写下的学习笔记. 向html页面中插入javascript代码的主要方法就是通过script标签.其中包括两种形式,第一 ...
- HTML 5 <script> 标签
HTML 4.01 与 HTML 5 之间的差异 async 属性是 HTML 5 中的新属性. 在 HTML 5 中,不再支持 HTML 4.01 中的一些属性. 提示和注释 注释:脚本按照如下方式 ...
- script标签里的defer属性
入职新公司,看代码的时候注意到有的script标签中有一个defer属性,查了一下.在这里分享出来. 需要注意的有三点,其中前两点是在错误中分辨出来的: 错误来源:http://www.w3schoo ...
随机推荐
- 【ARC077F】SS kmp+打表找规律
Description 如果某个串可以由两个一样的串前后连接得到,我们就称之为"偶串".比如说"xyzxyz"和"aaaaaa"是偶串, ...
- 洛谷P2287 [HNOI2004]最佳包裹(三维凸包)
题面 传送门 题解 左转板子,调个精度就能\(A\)了 //minamoto #include<bits/stdc++.h> #define R register #define fp(i ...
- J2EE 的体系结构
J2EE 即Java2平台企业版,它提供了基于组件的方式来设计.开发.组装和部署企业应用.J2EE使用多层分布式的应用模型,这个多层通常通过三层或四层来实现: 1.客户层,运行在客户计算机上的组件. ...
- 【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解
本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情 ...
- django基础知识之Response对象
HttpResponse对象 在django.http模块中定义了HttpResponse对象的API HttpRequest对象由Django自动创建,HttpResponse对象由程序员创建 不调 ...
- Android 数据库框架GreenDao使用
1.GreenDao3介绍 (1)基本概念 (2)GreenDao3工作原理 (3)GreenDao优点 (4)GreenDao3版本的改进 2.GreenDao3的相关配置概念介绍 (1)配置项目( ...
- IIS环境下上传文件失败
跟随学习代码练习 php 上传文件,一开始是点击按钮后没有反应,不知道是否成功,使用 var_dump($_FILES) 查看,发现空空如也.遂百度一下,发现基本代码应如下 <form acti ...
- Spring4 笔记
1. 通过 xml 赋值给 bean 1) 通过set 方法赋值 (必须要有空的构造方法) <bean id="user" class="com.test.User ...
- 【CTF】某xss练手小游戏
http://test.xss.tv 1.http://47.94.13.75/test/level1.php?name=test 直接插入即可,如: http://47.94.13.75/test/ ...
- web安全——文件上传
文件上传本身不是漏洞,但如果文件上传功能的限制出现纰漏,允许了不合法且影响网站安全的文件的上传 可以将不合法且影响网站安全稳定性的文件等内容上传的均为“文件上传漏洞” 黑方将文件上 ...