Summary
1. Chrome、Safari、Firefox、Opera 下,script 添加到 fragment 中时不会下载,添加
到 DOM 树中时才会下载并执行,并且执行上下文是全局环境,一切符合预期。
2. IE6-9 下,在 script 设置 src 属性时就会触发下载,添加到 fragment 或其他 DOM 节点
时会触发执行。执行时上下文是 fragment,相当于
with(fragment) { (function() { script code }).call(fragment) }
当有缓存时,情况更复杂,详见参考文档 [3]
3. 标准浏览器包括 IE9+ 下,fragment 没有 createElement 等方法,但在 IE6-8 下有。
4. IE10 与 Chrome 等标准浏览器表现一致,赞。
本来想利用 DocumentFragment 来解决 IE6-9 下获取 script 的 src 的问题,比如:
fragment['define'] = function(require, exports, module) {
// 很自然地得到了模块 id
module.id = script.src
// 调用 seajs 的 define
window.define(require, exports, module)
}
现在看起来带来的隐患很多。如果用 DocumentFragment 来动态插入 script,则 script code
在执行时,相当于
with(fragment) { (function() { script code }).call(fragment) }
a) script code 执行时多了一层闭包,这导致 var xx = ... 不再是全局变量。
b) script code 执行时的 this 是 fragment,不是 window,这会带来很多问题。
c) 多了一层闭包,如果 script code 代码不当,会导致内存泄露。
这样,利用 DocumentFragment 来动态插入 script,只适合纯数据的 JSONP,比如
define({
"a": "a",
...
})
上面这种情况下,利用 DocumentFragment 来实现 JSONP,简单方便,并能提升性能。
补充:不用 DocumentFragment 做容器,用普通 div 元素做容器,IE6-9 下会自动创建一个匿名
document,执行时变成
with(document) { (function() { script code }).call(document) }
问题依旧。
最后更新时间:2012-12-17
参考文档:
- https://developer.mozilla.org/en-US/docs/DOM/document.createDocumentFragment
- http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/
- http://www.guypo.com/technical/ies-premature-execution-problem/
- http://velocity.oreilly.com.cn/2012/ppts/xuxiao.pdf
- http://varnow.org/?p=152
- http://www.cnblogs.com/objectorl/archive/2009/08/05/1632718.html
- http://www.cnblogs.com/rubylouvre/archive/2012/12/16/2820372.html
- http://www.webshowme.com/04js/content.asp?id=1613