There seems to be a strange behavior in Javascript with hoisting and scoping , when using 'with' keyword.
I understand the usage of 'with' is considered taboo, but came across this in one of the frameworks and had to deal with it. But nonetheless,
Could anyone explain why if we have a 'with' block , the variables that are declared but undefined are resolved using the with object but this is not the case with the closure variables.
To demo, see the output of the following code: http://jsfiddle.net/ftK2Z/1/
var x = 90;
function test1(){
var address = {
street: 'Haight',
aptNum: 2
};
with (address){
alert(aptNum + ":" + x); // this outputs 2 : undefined.
var aptNum = 100,
x = 10 ;
}
}
Checked with google chrome.
Note: that I understand JS hoisting and see why having var statements after the alert is an issue but the main thing I am trying to figure out it is , during scope resolution at the alert statement, both 'aptNum' and 'x' should be undefined in local scope due to hoisting, so they should be taken as 'declared but not defined'.
But still, aptNum is output as '2'.
Inside the with
block, the variable aptNum
is shadowed by address.aptNum
, and x
refers to the local variable (never address.x
, as there isn't such a property).
Considering that, and hoisting, your code is equivalent to:
var x = 90;
function test1(){
var aptNum; // hoisted
var x; // hoisted
var address = {
street: 'Haight',
aptNum: 2
};
with (address){
// any reference to aptNum or street inside the with block
// is actually referencing address.aptNum and address.street
alert(aptNum + ":" + x); // this outputs 2 : undefined.
// as expected, because there is no address.x
// and the local x is undefined at this point
aptNum = 100; // this assigns to address.aptNum
// the variable aptNum is shadowed by address.aptNum
x = 10; // this assigns to the local x inside the function
// (again because there is no address.x)
}
}