移除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 ...
随机推荐
- springboot集成巨杉数据库
springboot倾向于约定优于配置,所以大大简化了搭建项目的流程,包括各种数据源的配置,接下来就和大家分享下最近用到的巨杉数据源连接池的配置 1.现在配置文件中定义巨杉连接池的各种连接信息,至于每 ...
- 从图片中提取html格式的布局
制作界面的自动化 意义:对于程序设计人员来说,比较痛苦的是制作界面.从设计人员发送的稿件(通常为jpg格式),到完成html的布局,需要将图像转化为div标记,自动化这一过程十分有意义 1.设计一个工 ...
- Python web前端 09 jQuery
Python web前端 09 jQuery 一.三个重要网址 http://jquery.cuishifeng.cn/ #中文查询网站 http://www.bootcdn.cn/ #引入jq ht ...
- POJ_2492 A Bug's Life 【并查集】
一.题面 POJ2492 二.分析 并查集判断类别的题目感觉套路都差不多. 还是先判断在不在一个集合里,在一个集合里才能判断是否同类. 若不在一个集合里则需要将这两个点联系起来. 关于联系起来后关系的 ...
- HDU 6336 (规律 + 二维矩阵的前缀和妙用)
题目 给出长度为n 的A矩阵 , 按 int cursor = 0; for (int i = 0; ; ++i) { for (int j = 0; j <= i; ++j) { M[j][i ...
- MongoDB基本语句
1.创建数据库 use 库名 2.查看所有库 show dbs 3.定义一个对象变量,下面挂着数据 4.col 是集合名,如果该集合不在该数据库中, MongoDB 会自动创建该 ...
- ActionHelper
/// <summary> /// 方法帮助类 /// </summary> public class ActionHelper { /// <summary> / ...
- vm 中安装 CentOS7
第三步:安装ISO文件 1.在vm下,文件,新建虚拟机 在我的机算机中,选中刚命名的CentOS7,右键,属性 2.开启虚拟机 PS: 打开虚拟机之后,提示了一个小错误,LZ根据错误提示,到BIOS里 ...
- Oracle列转行函数Listagg以及pivot查询示例
简单的Oracle列转行函数Listagg示例: CREATE TABLE tbl_test (catalog VARCHAR(1),product VARCHAR(2),amount NUMBER) ...
- 【总结】MYSQL注入
关于MYSQL注入的总结,网上的资料很多,这里和大家简单分享下自己实战中常用的思路和命令 0x00 UNION联合查询型注入常用语句 order by n //定字段,n为正整数 union se ...