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.