为什么这个JavaScript(使用document.open和document.write)不能在Internet Explorer或Opera中运行?

时间:2009-11-15 07:30:48

标签: javascript iframe scope document document.write

我迫切需要一些帮助。

我创建了一个< script>这与另一个更复杂的< script>的问题密切相关,并且再现了问题。我在其他地方写过。

以下是它的作用:

  • 创建< iframe>并插入< div>在页面上
  • 创建并将文档附加到< iframe>,其中包含< script>它定义了一些函数(包括一个回调函数和一个使用AJAX加载外部<脚本>的函数)
  • 后一个外部脚本只是对回调函数的调用,该函数调用一个创建文档并将其附加到< iframe>的函数。在里面;这应该有效地覆盖< script>

涉及的三个文件是:

这一切都适用于Firefox,Safari和Chrome。它崩溃的地方是Internet Explorer和Opera。会发生什么是main.js中的render()函数执行,并且触发了所有三个警报,但是< iframe>中的文档被触发了。没有被覆盖。我无法分辨出正在创建或写入的文档,或者根本不知道该文档。

如果我在render()函数的开头添加调试代码(如console.log(document)),那么工作浏览器似乎可以处理现有的< iframe>记录并列出下面包含的属性。 Internet Explorer似乎也可以找到某种文档。我只是不知道为什么不让我覆盖它。

这可能是范围问题吗?也许我正在不正确地使用document.write(),document.open()或document.close()方法,Firefox和其他一些浏览器只是让我逃脱它?

一个可能的线索:如果我把render()函数的内容拿出来(即,只需将它们放在main.js中的load()之后),这样就可以了。这告诉我,我不是如何使用document.open()等,但是在执行callback()函数时,文档对象不可用,或者超出了范围,或类似的东西。

这让我完全难过,这是一个非常重要的项目,即将到期。如果它让我摆脱这种干扰,我不会超越黑客或解决方法。任何帮助或见解都会非常感激!

console.log()的文档属性列表:

ATTRIBUTE_NODE: 2
CDATA_SECTION_NODE: 4
COMMENT_NODE: 8
DOCUMENT_FRAGMENT_NODE: 11
DOCUMENT_NODE: 9
DOCUMENT_POSITION_CONTAINED_BY: 16
DOCUMENT_POSITION_CONTAINS: 8
DOCUMENT_POSITION_DISCONNECTED: 1
DOCUMENT_POSITION_FOLLOWING: 4
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32
DOCUMENT_POSITION_PRECEDING: 2
DOCUMENT_TYPE_NODE: 10
ELEMENT_NODE: 1
ENTITY_NODE: 6
ENTITY_REFERENCE_NODE: 5
NOTATION_NODE: 12
PROCESSING_INSTRUCTION_NODE: 7
TEXT_NODE: 3
URL: "http://localhost/projects/test/ajax_loader/document_write/index.html"
activeElement: HTMLBodyElement
addEventListener: function addEventListener() {
adoptNode: function adoptNode() {
alinkColor: ""
all: HTMLCollection
anchors: HTMLCollection
appendChild: function appendChild() {
applets: HTMLCollection
attributes: null
baseURI: "http://localhost/projects/test/ajax_loader/document_write/index.html"
bgColor: ""
body: HTMLBodyElement
captureEvents: function captureEvents() {
characterSet: "UTF-8"
charset: "UTF-8"
childNodes: NodeList
clear: function clear() {
cloneNode: function cloneNode() {
close: function close() {
compareDocumentPosition: function compareDocumentPosition() {
compatMode: "BackCompat"
cookie: "__gads=ID=62bb88ab20ac9451:T=1256683145:S=ALNI_Mbso-nFjAvRzYhCSwhiuaDh84G8CA"
createAttribute: function createAttribute() {
createAttributeNS: function createAttributeNS() {
createCDATASection: function createCDATASection() {
createComment: function createComment() {
createDocumentFragment: function createDocumentFragment() {
createElement: function createElement() {
createElementNS: function createElementNS() {
createEntityReference: function createEntityReference() {
createEvent: function createEvent() {
createExpression: function createExpression() {
createNSResolver: function createNSResolver() {
createNodeIterator: function createNodeIterator() {
createProcessingInstruction: function createProcessingInstruction() {
createRange: function createRange() {
createTextNode: function createTextNode() {
createTreeWalker: function createTreeWalker() {
defaultCharset: "iso-8859-1"
defaultView: DOMWindow
designMode: "off"
dir: ""
dispatchEvent: function dispatchEvent() {
doctype: null
documentElement: HTMLHtmlElement
documentURI: "http://localhost/projects/test/ajax_loader/document_write/index.html"
domain: "localhost"
elementFromPoint: function elementFromPoint() {
embeds: HTMLCollection
evaluate: function evaluate() {
execCommand: function execCommand() {
fgColor: ""
firstChild: HTMLHtmlElement
forms: HTMLCollection
getCSSCanvasContext: function getCSSCanvasContext() {
getElementById: function getElementById() {
getElementsByClassName: function getElementsByClassName() {
getElementsByName: function getElementsByName() {
getElementsByTagName: function getElementsByTagName() {
getElementsByTagNameNS: function getElementsByTagNameNS() {
getOverrideStyle: function getOverrideStyle() {
getSelection: function getSelection() {
hasAttributes: function hasAttributes() {
hasChildNodes: function hasChildNodes() {
hasFocus: function hasFocus() {
height: 150
images: HTMLCollection
implementation: DOMImplementation
importNode: function importNode() {
inputEncoding: "UTF-8"
insertBefore: function insertBefore() {
isDefaultNamespace: function isDefaultNamespace() {
isEqualNode: function isEqualNode() {
isSameNode: function isSameNode() {
isSupported: function isSupported() {
jQuery1258269389622: 2
lastChild: HTMLHtmlElement
lastModified: ""
linkColor: ""
links: HTMLCollection
localName: null
location: Location
lookupNamespaceURI: function lookupNamespaceURI() {
lookupPrefix: function lookupPrefix() {
namespaceURI: null
nextSibling: null
nodeName: "#document"
nodeType: 9
nodeValue: null
normalize: function normalize() {
open: function open() {
ownerDocument: null
parentElement: null
parentNode: null
plugins: HTMLCollection
preferredStylesheetSet: null
prefix: null
previousSibling: null
queryCommandEnabled: function queryCommandEnabled() {
queryCommandIndeterm: function queryCommandIndeterm() {
queryCommandState: function queryCommandState() {
queryCommandSupported: function queryCommandSupported() {
queryCommandValue: function queryCommandValue() {
querySelector: function querySelector() {
querySelectorAll: function querySelectorAll() {
readyState: "complete"
referrer: "http://localhost/projects/test/ajax_loader/document_write/index.html"
releaseEvents: function releaseEvents() {
removeChild: function removeChild() {
removeEventListener: function removeEventListener() {
replaceChild: function replaceChild() {
scripts: HTMLCollection
selectedStylesheetSet: null
styleSheets: StyleSheetList
textContent: null
title: " Page"
vlinkColor: ""
width: 300
write: function write() {
writeln: function writeln() {
xmlEncoding: null
xmlStandalone: false
xmlVersion: null

6 个答案:

答案 0 :(得分:11)

  

如果我把render()函数的内容拿出来(也就是说,只需将它们放在main.js中的load()之后),这样就可以了。

在IE8中不适合我。如果我完全丢失了AJAX调用并且只是在main.js中调用render(),我会得到相同的结果。实际上,即使我用以下内容替换整个main.js:

document.write('hello!');

无论是否打开文件,都不会出现问候!

如果我在main.js中调用render时发出任何超时(甚至0),它就可以正常工作。另一方面,父文档的超时似乎没有做任何事情。

这种极端的怪异是由jQuery使用临时插入的<script>标记来执行jsonp.js中返回的代码引起的。如果你只是在返回值上调用eval而不是让jQuery执行它,它就可以正常工作。

我发现缩小hello示例的相关问题由index.html证明:

<body>
<iframe name="foo"></iframe>
<script>
    var idoc= frames['foo'].document;
    idoc.open();
    idoc.write('<body><script src="main.js"><\/script>');
    idoc.close();
</script>

main.js包含:

document.write('foo');

没有写过foo。 (另一方面,内联脚本很好。)

如果idoc.close被省略,那就有效了。如果添加了额外的idoc.write('bar'),则bar仅在IE中foo之前编写。如果我添加了barclose调用,则IE崩溃。

总而言之,在document.write编写的文档中使用document.write存在深层问题!尽可能避免使用它。 document.open可以是从父文档填充iframe的有用方法,但您不应该在子文档中真正需要它,您可以在自己使用DOM方法。

答案 1 :(得分:4)

正如大多数人已经介绍的那样,IE在尝试做一些简单的事情时会遇到严重问题:

var doc = window.frames['your_frame'].document;
doc.open();
doc.write('<body><script src="external_resource.js"><\/script>');
doc.close();

经过详尽的搜索后,我发现这个this write-up建议使用javascript:URI方案将内容插入到iframe文档中。我个人在当前版本的FF,Chrome和&amp ;;中测试了这个解决方案。 Safari,以及IE 7/8/9/10。

借用他的例子,下面的代码将取代我上面的例子,可以用来实现你的目标:

var iframe = window.frames['your_frame'];
var content = '<body><script src="external_resource.js"><\/script>';
iframe.contentWindow.contents = content;
iframe.src = 'javascript:window["contents"]';

我听说它说老版本的Safari不能很好地处理javascript:URI方案,但我无法找到确认方法,因为使用Safari的每个人似乎都经常升级。我也不知道这是否会影响IE中URI的字符限制问题(因为它比其他所有浏览器都要小),但是值得研究那些遇到类似问题的人。

答案 2 :(得分:2)

根本问题是IE中的你无法做到

iframe_document.open();
iframe_document.write('<script src="foo.js"><\/script>');
iframe_document.close();

在iframe上调用document.close()之后,IE似乎暂停了所有javascript执行。 js线程运行document.close(),而foo.js的http请求未完成,因此文件已加载但从未执行过。

我没有找到任何方法让父页面知道在iframe中执行的脚本已完全完成。一个解决办法就是让foo.js负责调用document.close()本身 - 不是很愉快,但是如果你不介意改变被调用的脚本,它就可以解决问题。

注意:你不能将document.write('document.close()')直接导入iframe: 会导致IE难以挂起。但是setTimeout(function(){document.close()},0)似乎是免疫的 - 就像加载的脚本中的document.close()有时一样。啊。

答案 3 :(得分:1)

您应该使用"src"属性加载iframe的内容:iframe的正文由不支持iframe的浏览器使用,以显示替代消息。相反,您将在iframe中注入一个完整的内联html文档,而某些浏览器则不喜欢它。 更多信息here

如果您想从主文档向iframe发送消息,可以在John Resig's blog上找到一个很好的教程。

答案 4 :(得分:0)

会像以下一样简单:

function render(data) {
    document.body.innerHTML = data;
}

解决你的问题?适用于IE8 / Win7。

答案 5 :(得分:0)

这很奇怪,迈克尔克莱伯错了:所有的警报都很好,所以问题不在于脚本没有执行。它确实执行。

观察main.js的以下更改:

$(document).ready(function() {

  // note that render() has to be moved into the window scope
  window.render = function(data) {
    document.open();
    alert('opened');
    document.write(data);
    alert('written');
    document.close();
    alert('closed');
  }

  function load() {
    $.ajax({
      url: 'jsonp.js',
      dataType: 'script'
    });
  }

  window.callback = function(data) {
    // does not work
    render(data);

    // works
    window.data = data;
    var t = setTimeout("render(data)", 0);
  }

  load();

});