JavaScript中的window.open无法工作

5

我想使用 window.open 打开一个 JSP 文件的窗口,但浏览器不停地显示 连接中...。每次点击文本时,甚至 firebug 停止工作。不论是 p 还是 input 标签都无效,但当我使用 href 链接 JSP 文件时,它可以链接到该文件:

<!DOCTYPE html>
<html>
<head><title>Sample JSP Page</title>
<script>
function open(){
    //window.open("hello.jsp","hello","height=700, width=800");
    var x=window.open("hello.jsp","window","status=1,height=700, width=800");
    x.focus();
}
</script>
</head>
<body>
<h1>Sample JSP Page</h1>
<p onclick="open()">do not work</p>
<form>
<input type="button" value="new window" onclick="window.open('test-with-utils')"></form>
</body>
</html>

2
你可能需要将open()函数重命名,因为它与window.open()在同一作用域中。 - Francis Nepomuceno
4个回答

10

这是因为您在定义函数 open 时重新定义了 window.open。请改用不同的函数名称。


非常聪明!我也曾经花了一些时间面临类似的问题。谢谢你! - rigon
救命稻草。刚刚遇到了这个:P - Michael Tontchev

6

修改函数名称。


5

窗口对象是JavaScript中的顶层对象,并包含其他几个对象,例如“document”,“history”等。

当您定义自己的变量或函数时,您实际上向窗口对象添加了新属性。 这将起作用(以及一个小的示例):

var foo = "bar";
alert ( window.foo ); // says "bar"

此外,如果您将以下小段代码添加到您的代码中:
window.onerror = function ( msg, url, num ) {
   alert ( "Error: " + msg + "\nURL: " + url + "\nLine: " + num );
   return true;
};

当您按下按钮时,您将会收到此错误:
Error: Uncaught RangeError: Maximum call stack size exceeded

这意味着无限递归。这是一种副作用——您定义了一个新的打开函数,当您调用window.open()时,您会递归调用自己的函数。

1

为了更详细地解释您在这里遇到问题的原因,您可能想要阅读一些关于JavaScript作用域的内容(非常有帮助的博客)。本质上,考虑以下代码:

<script>
var thisOne=true;
function thatOne() {
alert("whizbang");
}
var theOther={foo:"bar"};

//More code here...
</script>

一旦您到达评论部分,您就知道可以直接访问那些变量和函数,例如if (thisOne) {...}element.onclick=thatOne;console.log(theOther.foo)。但是,您也可以将它们作为根对象的子级来访问,在Web浏览器中称为window。因此,您可以执行以下操作:

console.log(window["thisOne"]);
window.thatOne.call(obj, params);
console.log(window.foo.bar);

通过将open()定义为不在另一个元素内(也就是说,在根元素内),您覆盖了window.open()函数。当您尝试稍后调用该函数时,会出现问题,因为open函数调用window.open,而window.open又调用window.open,依此类推...

有几种方法可以解决这个问题 -

内联定义onclick处理程序

要做到这一点,请摆脱整个<script>..</script>元素,然后使用任何支持它的元素添加onclick属性:

onclick="window.open('hello.jsp','window','status=1,height=700, width=800');"

这是一个不错和快速的方法,并且它将所有逻辑都与触发元素保持在一起,但是它并不容易扩展,你可能会被某些人嘲笑。(“哦,你用内联javascript? 多么古怪")

更改方法名称

从现有的代码中修改open()方法名称为openANewWindow()或gotoJSP()等不存在于根对象中的名称即可,这是花费最少的修改成本(这基本上是其他所有人建议的方法)。确保同时在定义方法(在脚本元素中)和使用方法(在onclick属性中)时都要修改。

使用闭包

对于单个函数而言,这几乎肯定不是您想要的,因为它比您需要的复杂得多。只是作为一个示例,说明如何跳出根对象,因为似乎处于根对象中是您的问题的核心。

您可能已经在JavaScript中看到了如何定义对象,但您可能不知道通过定义对象,您真正做的只是向根对象添加一个对象属性。您可以利用这种行为,给您的函数赋予分层结构。

例如:

<script>
var MyFunctions = (function() {
    function open(){
    var x=window.open("hello.jsp","window","status=1,height=700, width=800");
    x.focus();
    }
    return {open:open};
})();
</script>

这将创建一个立即运行的匿名函数。在该函数的作用域内,定义了另一个函数open(),但是它是在匿名函数的作用域内定义的,而不是根对象(window)中定义的。在定义open()之后,将其引用作为对象属性open的值返回:

所有这些的结果是MyFunctions对象的open属性是您需要的函数。然后,您可以使用MyFunctions.open()或甚至window.MyFunctions.open()来调用它。


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