为什么谷歌浏览器无法运行这段JavaScript代码?

9
当我在Chrome(版本2)中运行此代码时,它不会返回字符串,但在Firefox(版本3)中可以正常工作。为什么会这样?
<html>
<head>
<script type="text/javascript">
function disp_prompt() {
    var name=prompt("Please enter your name","Harry Potter");
    if (name!=null && name!="") {
        document.write("Hello " + name + "! How are you today?");
    }
}
</script>
</head>
<body>

<input type="button" onclick="disp_prompt()" value="Display a prompt box" />

</body>
</html>

我相信你可以将 'if (name != null && name != "")' 这个语句简化为 'if (name)'。 - Steve Harrison
4个回答

32

如果要向文档附加内容,应该只在<script>块解析阶段调用document.write()

如果您在执行操作的上下文之外(例如在事件处理程序中)调用document.write,则不会进行解析,因此字符串'foo'无处可去。

根据原始JavaScript参考文献的规定:

事件处理程序在原始文档关闭后执行,因此如果您在事件处理程序中未显式发出document.open方法,则write方法会隐式打开一个mimeType为text/html的新文档。

也就是说,它假设您犯了一个错误并且意味着执行:

document.open('text/html');
document.write(html);

这会用新内容替换整个文档。同时你会注意到,因为你没有调用以下方法完成相关操作:

document.close();

在Firefox中,“loading”动画仍在旋转,期望会有更多的内容被写入文档(但实际上没有)。

在这种情况下,您正在使用document.write()向文档写入字符串:

Hello bobince! How are you today?

这明显不是一个有效的HTML文档。Chrome(和表现相同的Safari)试图将其解析为HTML文档,但由于在文档元素(<html>)之外存在非空格文本内容,因此失败了,这是不被允许的。如果在名称输入中添加一些标记:

Hello <em>bobince</em>! How are you today?

你会看到<em>元素外的所有内容都被丢弃。Firefox和IE成功地应用了他们的“修复在任何元素外部的文本”破损HTML规则来帮助你,但Chrome不行。

如果你想用document.write()编写新文档,请确保它确实是一个完整的文档:

<html><head><title>Greetings</title><body><p>Hello bobince! How are you today?</p></body></html>

或者,如果你想要用 document.write() 输出文本字符串,理论上应该调用:

document.open('text/plain');

在 write() 函数之前。但是请注意,Chrome 或 Safari 不支持 mimetype 参数;它们会始终将您编写的内容视为 HTML。

无论如何,您可能不想使用这种方法。如果您想要添加或更改现有页面,通常应该使用 DOM 方法,例如在状态输出 div 上设置文本,或使用 innerHTML 替换 body 内容。

document.write() 在某些情况下是必需的(特别是当您从头创建新窗口或帧时),但除此之外,它通常是错误的,应受到怀疑。


谢谢!谢谢!谢谢!(我希望有一种选项可以给单个答案10个投票:我花了整整一个星期搜索和阅读如何解决JavaScript执行从ajax检索到的页面替换整个文档的问题...如果早些时候我在Chrome上搜索document.write JavaScript执行问题就好了!!) - NotGaeL

9
不要使用 document.write。如果你将它更改为像下面这样的东西:
if (name != null && name != "") {
    document.getElementById('foo').innerHTML = "Hello " + name + "! How are you today?";
}

<body>
<input ...

<div id='foo'> </div>
</body>

document.write有着相当奇怪的行为。你期望文本会被写到哪里呢?


我认为在“!今天过得如何?”后面有一个额外的括号。 - Steve Harrison
哦,我刚刚开始通过网络教程学习JavaScript。谢谢你的提示! - ehfeng
我以为这段文本只是应该写到浏览器窗口中。 - ehfeng
@KentFredric 有时候我也遇到过只有使用 document.write 才能解决问题的情况,所以请记住有时候它可能会让你的生活更轻松。 - eric.itzhak

2

只需在写入调用中添加一些段落标记:

<html>
<head>
<script type="text/javascript">

function disp_prompt() {
    var name = window.prompt("Please enter your name", "Harry Potter");
    if (name) {
        window.document.write("<p>Hello " + name + "! How are you today?<\/p>");
    }
}
</script>
</head>
<body>

<input type="button" onclick="disp_prompt()" value="Display a prompt box" />

</body>
</html>

0
有点晚了,但我在Chrome DevTools中看到了一个关于document.write()的违规链接。毋庸置疑,这是一篇有趣的文章。
这是关于什么的?
从Chrome v55开始,在非常特定的情况下,Chrome将开始阻止document.write()。您可以在此处阅读有关此问题的更多信息:

https://developers.google.com/web/updates/2016/08/removing-document-write

这应该仅对使用2G蜂窝连接的用户以及可能其他速度较慢的连接产生影响。以下是相关文章的摘录:

有了这些数据,Chrome从版本55开始,当检测到已知的恶意模式时,代表所有用户进行干预,通过更改Chrome中处理document.write()的方式(请参见Chrome状态)。具体来说,当满足以下所有条件时,Chrome不会执行由document.write()注入的元素:
  1. 用户连接缓慢,特别是用户使用2G时。(将来可能会扩展到其他用户使用缓慢的连接,如缓慢的3G或缓慢的WiFi。)
  2. document.write()在顶级文档中。干预不适用于iframe内的document.written脚本,因为它们不会阻止主页面的呈现。
  3. document.write()中的脚本阻止解析器。带有“async”或“defer”属性的脚本仍将执行。
  4. 脚本未托管在同一站点上。换句话说,对于具有匹配eTLD+1的脚本(例如插入在www.example.org上的js.example.org上托管的脚本),Chrome不会进行干预。
  5. 脚本尚未在浏览器HTTP缓存中。缓存中的脚本不会产生网络延迟,并且仍将执行。
  6. 页面请求不是重新加载。如果用户触发了重新加载,则Chrome不会进行干预,并将页面视为正常执行。
第三方片段有时使用document.write()来加载脚本。幸运的是,大多数第三方提供异步加载替代方案,这允许第三方脚本在不阻止页面其余内容显示的情况下加载。

如果您的document.write()符合所有6个标准,那么Chrome将会阻止它。当它发生时,您应该能够在DevTools中看到消息。

OP的问题

为了回答OP的问题,您需要先使用document.open("text/html")来使用document.write()。完成文档编写后,您需要使用document.close()。 如果您只想编写纯文本,则使用document.open("text/plain")。然而,我最近在某处读到Chrome忽略MIME类型并强制使用text/html。

<html>
<head>
<script type="text/javascript">
function disp_prompt() {
    var name=prompt("Please enter your name","Harry Potter");
    if (name!=null && name!="") {
        document.open("text/plain");
        document.write("Hello " + name + "! How are you today?");
        document.close();
    }
}
</script>
</head>
<body>

<input type="button" onclick="disp_prompt()" value="Display a prompt box" />

</body>
</html>

--或者--

您可以修改您编写的文本,以包含正确的HTML,就像这样:

document.write('<html><head></head><body>Hello ' + name + '! How are you today?</body></html>');

不要忘记在所有情况下添加document.open()document.close()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接