我打开一个窗口,想要在某些条件下执行一些计算。
问题出现在IE中,只有第一次调用test
(来自ready
)才能从新窗口执行,
但后续调用test
(使用setTimeout设置)在父窗口中执行,而不是在新窗口中执行(即win
)。
它在FF中运行良好。
说明代码(此代码在父窗口中):
var win = window.open(some_url, window_name, argument_string);
with (win) {
function test() {
alreadyrunflag += 1;
if (alreadyrunflag < 10) {
window.setTimeout(function() { test(); }, 500);
}else {
//perform calculation
}
}
jQuery(win.document).ready(function() {
alreadyrunflag = 0
test();
});
}
答案 0 :(得分:5)
我会强烈建议不要在这种情况下使用with
(坦率地说,几乎任何其他情况)。相反,只需在必要的地方写win.
即可。像埃里克迈耶一样,我是not a huge fan“被认为有害”的文章,但道格拉斯克罗克福德this one我完全同意。
with
修改“范围链”,使得需要严格掌握JavaScript的高级知识才能完全理解。有关详细信息,请参阅Crockford的文章。它还引入了速度惩罚(尽管已经批准了,虽然我听到人们对它们大肆宣传,但我怀疑成本确实 高)。对可维护性的影响是不可接受的。此外,您无法在新的严格模式(MDC link)中使用它,这是一种有用的模式,可以帮助您避免一些常见的错误。
在这种情况下,在我看来,范围链应该以您期望的方式解决(以及Firefox显然正在这样做的方式),但坦率地说,我对IE的JScript实现并不感到震惊。以同样的方式处理它。和/或它可能是jQuery
最终被使用的问题(打开窗口中的那个或刚刚打开的窗口中的那个;你不能确定,它将取决于时间...呸)。
答案 1 :(得分:4)
在function
,if
或for
之类的结构中放置with
声明 - 除了直接在函数体或全局范围内的任何位置 - 在ECMAScript中无效基本的语法水平。浏览器通常会让您逃脱它,但是当您执行操作时实际发生的事情因浏览器而异,因此您永远不应该依赖它。
此案例演示了其中一个问题:在Firefox中,function
语句被解释为非标准的Mozilla JavaScript扩展FunctionStatement
,它将其视为您使用{{1}你期望的时候评估内联。
但是在IE中,FunctionExpression
语句的解释方式与kosher function
和'hoisted'相同:在包含它的函数的开头计算。它没有将FunctionDeclaration
语句的值作为额外范围获得(即使它已经,with
尚未分配,因此您将win
放在范围链上!)。
所以可以通过明确使用undefined
来解决它:
FunctionExpression
但我真的不推荐它。正如TJ所说,with (win) {
test= function() { ... };
}
绝对糟透了。它在ECMAScript第五版的严格模式中被废除了。不要使用它。 (以及评论中提到的时间问题。确实如此。)
如果您真的想将with
注入子窗口,请直接说:test
。但是,我认为没有必要这样做。您可以从外部完美地查看子窗口,而无需将该函数的副本放在子窗口的属性中。即使您这样做,也不会改变函数中代码的范围。从文档中提供其他文档中的函数副本就像在IE中一样狡猾,如果文档被卸载,那么该文档中定义的所有函数都会中断。