繁体   English   中英

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

[英]Why won't this JavaScript (using document.open and document.write) work in Internet Explorer or Opera?

我迫切需要一些帮助。

我创建了一个非常平行的<script>,并重现了我在其他地方写过的另一个更复杂的<script>的问题。

这是它的作用:

  • 创建一个<iframe>并插入页面上的<div>
  • 创建文档并将其附加到<iframe>,其中包含定义一些函数的<script>(包括回调函数和使用AJAX加载外部<script>的函数)
  • 后一个外部脚本只是对回调函数的调用,该函数调用一个创建文档并将其附加到<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

如果我把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') ,则仅在IE中的foo之前编写该bar 如果我添加了barclose调用,IE崩溃了。

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

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

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

详尽的搜索后,我发现这这写这表明使用JavaScript:URI方案插入内容到IFRAME文档。 我亲自在当前版本的FF,Chrome和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的字符限制问题(因为它比其他所有浏览器都要小),但是值得研究那些遭遇类似问题的人。

根本问题是在IE中你做不到

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

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

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

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

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

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

会像这样简单:

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

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

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

观察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();

});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM