with(window){}不适用于IE中的新弹出窗口

时间:2010-10-28 10:41:19

标签: javascript

我打开一个窗口,想要在某些条件下执行一些计算。 问题出现在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();          
    });
}

2 个答案:

答案 0 :(得分:5)

我会强烈建议不要在这种情况下使用with(坦率地说,几乎任何其他情况)。相反,只需在必要的地方写win.即可。像埃里克迈耶一样,我是not a huge fan“被认为有害”的文章,但道格拉斯克罗克福德this one我完全同意。

with修改“范围链”,使得需要严格掌握JavaScript的高级知识才能完全理解。有关详细信息,请参阅Crockford的文章。它还引入了速度惩罚(尽管已经批准了,虽然我听到人们对它们大肆宣传,但我怀疑成本确实 高)。对可维护性的影响是不可接受的。此外,您无法在新的严格模式(MDC link)中使用它,这是一种有用的模式,可以帮助您避免一些常见的错误。

在这种情况下,在我看来,范围链应该以您期望的方式解决(以及Firefox显然正在这样做的方式),但坦率地说,我对IE的JScript实现并不感到震惊。以同样的方式处理它。和/或它可能是jQuery最终被使用的问题(打开窗口中的那个或刚刚打开的窗口中的那个;你不能确定,它将取决于时间...呸)。

答案 1 :(得分:4)

functioniffor之类的结构中放置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中一样狡猾,如果文档被卸载,那么该文档中定义的所有函数都会中断。