繁体   English   中英

Javascript中的范围解析使用'with'关键字

[英]Scope resolution in Javascript using 'with' keyword

当使用'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语句是一个问题,但我想弄清楚的主要问题是,在alert语句的范围解析期间,'aptNum'和'x'都应该是由于吊装而在本地范围内未定义,因此它们应被视为“已声明但未定义”。

但是,aptNum输出为'2'。

with块中,变量aptNumaddress.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)
    }
}

从小提琴:

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

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

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

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

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

var x = 90;
test(x);

示例: jsFiddle

有关JavaScript的更多信息

我猜你甚至在声明x之前调用了x (它将被视为address的属性)。 xwith范围不指x的功能外声明。 当然,引擎正在尝试读取当前不存在的address.x的值。 这就是原因。 关于with ,因为aptNum是“re',宣布为在该范围内的变量,它并不是指addressaptNum

编码

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

var -ing aptNumx的内with var被提升,所以它也可以被视为

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

现在很容易理解为什么它们是undefined 你可能不想在这里使用var

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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