简体   繁体   中英

with (window) {} doesn't work for new pop-up window in IE

I open a window, and want to perform some calculation on some condition. Problem is in IE, only first call of test (from ready ) is performed from new window, but subsequent calls of test (set with setTimeout) are executed in parent window and not for new window (ie win ).

It works fine in FF.

illustrating code (this code is in parent window):

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();          
    });
}

I would strongly recommend against using with in this situation (and, frankly, almost any other). Instead, simply write win. everywhere necessary. Like Eric Meyer, I'm not a huge fan of "considered harmful" essays, but this one by Douglas Crockford I'm in full agreement with.

with modifies the "scope chain" in a way that it takes a seriously advanced knowledge of JavaScript to understand fully. See Crockford's essay for details. It also introduces speed penalties (though granted, while I've heard people rant about them, I doubt the costs are really that high). The effects on maintainability are just unacceptable. Also, you can't use it in the new strict mode ( MDC link ), which is a useful mode that helps you avoid some common bugs.

In this case, it seems to me that the scope chain should resolve in the way you're expecting (and the way Firefox apparently is doing it), but frankly I'm not shocked at all that IE's JScript implementation doesn't handle it the same way. And/or it may be an issue with which jQuery ends up getting used (the one in the opening window or the one in the just-opened window; you can't be sure, and it would be timing-dependent...yuck).

Putting a function declaration in a structure like if , for or with —anywhere other than directly inside a function body or global scope—is invalid in ECMAScript on a basic grammar level. Browsers typically let you get away with it, but what actually happens when you do varies from browser to browser, so you should never rely on it.

This case demonstrates one of the problems: in Firefox, the function statement is interpreted as the non-standard Mozilla JavaScript extension FunctionStatement , which treats it as if you'd used a FunctionExpression , evaluated inline when you expected.

But in IE, the function statement is interpreted in the same way as a kosher FunctionDeclaration and 'hoisted': evaluated at the start of the function that contains it. It does not gain the with statement's value as an extra scope (and even if it did, win hasn't been assigned yet, so you'd be putting undefined on the scope chain!).

So you could get around it by using the FunctionExpression explicitly:

with (win) {
    test= function() { ... };
}

But I'd seriously not recommend it. As TJ said, with absolutely sucks. It's abolished in ECMAScript Fifth Edition's Strict Mode. Don't use it. (And the timing issues mentioned in the comments. Yuck indeed.)

If you really want to inject test into the child window, say so directly: win.test= function() { ... }; . However, I don't see any need to do so here. You can perfectly well look at the child window from outside without having to put a copy of the function in a property of the child window. Even if you do so, it won't change the scope of the code in the function. And giving documents a copy of functions from other documents is dodgy as in IE, if a document is unloaded, all the functions defined in that document break.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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