移除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系列无一例外的报错,而标准浏览器却可以正常引用。

时间: 2024-11-06 16:47:42

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

Javascript跨域解决方案之script标签实现

/********************************************************** 说明:跨域请求数据Javascript组件 ---------------------------------------------------------- add by 傻帽儿 2015-4-13 18:18:14 **********************************************************/ ; (function (window

JavaScript之&lt;script&gt;标签简介

向html页面中插入JavaScrpt的主要方法,就是使用<script>元素,下面是Html 4.01为<script>定义的6个属性. 1.async:可选表示应该立即下载脚本,但是不妨碍页面中的其他操作,比如下载比如下载其他资源或等待加载其他脚本.这个属性只对外部脚本有效 2.charset:可选.表示脚本通过src属性指定的代码的字符集.大多数浏览器会忽略它的值,所以这个属性也很少用. 3.defer:可选.表示脚本可以延迟到文档完全被解析和显示之后在执行.只对外部脚本有效

javascript正则找script标签, link标签里面的src或者 href属性

1. [代码]javascript 简单的search    <script(?:(?:\s|.)+?)src=[\"\'](.+?)[\"\'](?!\<)(?:(?:\s|.)*?)(?:(?:\/\>)|(?:\>\s*?\<\/script\>)) <script  src="sdfsdf/sdfd.js"          type="text/javascript"  /><scr

js中的script标签

在页面中用script标签引入javascript文件(<script type="text/javascript" src="js文件地址"></script>),浏览器在渲染页面的时候,当读取到script元素时,浏览器不会以HTML或XHTML的方式处理其内容,浏览器会通知浏览器的脚本引擎来接管script元素中的内容.   script元素的type属性定义脚本类型,type类型有: 1.text/ecmascript(表示以ECMA

HTML 5 &lt;script&gt; 标签

HTML 4.01 与 HTML 5 之间的差异 async 属性是 HTML 5 中的新属性. 在 HTML 5 中,不再支持 HTML 4.01 中的一些属性. 提示和注释 注释:脚本按照如下方式执行: 如果 async 属性为 true,则脚本会相对于文档的其余部分异步执行,这样脚本会在页面继续解析的过程中执行. 如果 async 属性为 false,而 defer 属性为 true,则脚本会在页面完成解析后执行. 如果 async 和 defer 属性均为 false,那么脚本会立即执行

关于&lt;Script&gt;标签在html页面放置位置

一般script标签会被放在头部或尾部.头部就是<head></head>里面,尾部一般指<body></body>里,但也有放在</body>闭合标签之后的.究竟这些位置不同有什么不一样呢?下面我来详细说一下:1.<script></script>标签放置在<head></head>标签内部时: 将script放在<head>里,浏览器解析HTML,发现script标签时,会先下载完所

script标签中的async和defer

在程序中代码是一行一行执行的,html标签都是由渲染引擎来执行,代码执行时从上往下一行一行执行,当执行到alert(如下图),alert会阻塞后面代码的执行,当点击完确定之后,代码继续往下执行. javascript的内容同样可在外部进行引用,如下图所示,正常情况下执行结果和上面的内容相同,但当我们给html的script标签中加入async或者defer属性时,代码的执行过程也将会随之改变. async 为异步,顾名思义就是多个人同时做多件事,这里区分sync,sync为同步,就是一个人有序的

javascript基础语法(简介、script标签、严格模式、保留字关键字)

[简介][1]定义:一种专为与网页交互而设计的脚本语言,也就是解释型编程语言.[2]组成: [2.1]ECMAScript由ECMA-262定义,提供核心语言功能(ECMA是欧洲计算机制造商协会) [2.2]DOM文档对象模型,提供访问和操作网页内容的方法的接口 [2.3]BOM浏览器对象模型,提供与浏览器交互的方法的接口 [script标签] [1]使用方式:引入外部文件和在页面内嵌入js代码[2]注意:带有src属性的<script>元素不应该在其<script>标签之间再包含

js 替换 script 标签内容,包括 换行符

这几天在做项目的时候需要用到js替换 script 标签内的内容 用自己写的字符串去匹配都能成功,但是一旦将大串的DOM内容去匹配的时候 却一直提示失败. 上网查了很多资料,一直匹配不了,调试了很久 郁闷的时候,灵光一闪,难不成是换行的问题,一测试,果然如此 var str = 'lkjkjk' +'<SCRIPT type=text/html> abc </SCRIPT>' var reg = /<script.*>.*<\/script>/gi aler