1

当使用 'with' 关键字时,Javascript 中似乎有一个奇怪的行为,带有提升和作用域。

我知道“with”的使用被认为是禁忌,但在其中一个框架中遇到了这一点,不得不处理它。但尽管如此,

谁能解释为什么如果我们有一个“with”块,声明但未定义的变量是使用 with 对象解析的,但闭包变量不是这种情况。

要演示,请参阅以下代码的输出: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 ;
    }
}

用谷歌浏览器检查。

注意:我了解 JS 提升,并了解为什么在警报之后使用 var 语句是一个问题,但我想弄清楚的主要是,在警报语句的范围解析期间,'aptNum' 和 'x' 都应该是由于提升,在本地范围内未定义,因此应将它们视为“已声明但未定义”。

但是,aptNum 仍然输出为“2”。

4

5 回答 5

2

with块内部,变量aptNum被 , 遮蔽address.aptNum,并x引用局部变量(从不address.x,因为没有这样的属性)。

考虑到这一点并提升,您的代码相当于:

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)
    }
}
于 2013-05-15T23:49:39.390 回答
1

不推荐使用 with,并且在 ECMAScript 5 严格模式下被禁止。推荐的替代方法是将要访问其属性的对象分配给临时变量。

它不喜欢有一个全局变量。我认为这是因为 x 超出了地址对象的范围。您可以将参数传递给函数并且它可以工作。

var x = 90;
test(x);

示例:jsFiddle

有关使用JavaScript 的更多信息

于 2013-05-15T23:40:19.973 回答
1

从小提琴:

with(address){
    $('#output').text('aptNum : ' + aptNum + ",   x : " + x ); 
    var aptNum = 100,
        x = 10 ;
}

该变量x正在语句的主体中重新with声明(参见前面的var关键字)。变量声明被提升,因此x被临时定义为,然后在值已被记录后undefined最终重新定义为。10

在这个更新的小提琴中,我将变量声明语句更改为一个简单的赋值语句,它产生了记录xto be值的预期行为90。见http://jsfiddle.net/ftK2Z/3/

于 2013-05-15T23:29:12.837 回答
0

编码

alert(aptNum + ":" +  x);
var aptNum = 100,
      x = 10 ;

is var-ingaptNum并且xwith. var被吊起所以它也可以被认为是

var aptNum, x;
alert(aptNum + ":" +  x);
aptNum = 100, x = 10;

现在很容易看出它们的原因undefined。你可能不想在var这里使用。

于 2013-05-15T23:34:12.810 回答
0

我猜你x甚至address在声明x. xwith范围内并不指x在函数外声明的。当然,引擎正在尝试读取address.x不存在的值。这就是原因。关于with,由于aptNum're' 被声明为该范围内的变量,因此它不引用address's aptNum

于 2013-05-15T23:32:21.460 回答