带“ with”语句和调用的一些复杂行为

凯伦·格里戈良(Karen Grigoryan)
var a = ({
    x: 10,
    foo: function () {
        function bar() {
            console.log(x);
            console.log(y);
            console.log(this.x);
        }
        with (this) {
            var x = 20;
            var y = 30;
            bar.call(this);
        }
    }
}).foo();

结果为undefined,30,20

非常感谢您逐步了解调试方式,以了解其工作原理。

贝吉

好了,让我们先简化一下代码。我已经将其重构foo为一种方法,不必证明这种意外行为。

function foo(a) {
    // var x, y, bar - hoisting
    function bar() {
        console.log(x);
        console.log(y);
        console.log(a.x);
    }
    with (a) {
        var x = 20;
        var y = 30;
        bar();
    }
}
foo({x:10});

那么,当我们打电话时会发生什么foo呢?

  1. 建立执行上下文,并用声明的函数和变量填充。这就是俗称的“吊装”。在中foo,有函数bar和变量xy(以及函数foo本身及其参数a,仅在我的重构版本中)。这是bar可以访问的范围
  2. with语句被执行。它与基于a对象的环境交换当前的词法环境-可以像访问变量一样访问其任何属性。
  3. 该值20分配给x这是x什么 解析该标识符时,将a检查对象,并且-哦-它具有与该名称的绑定!因此,我们将值放在该绑定中,这会将对象20.x属性放在
  4. 该值30分配给y这是y什么 再次检查当前的词法环境,但我们ya对象找不到属性所以,我们去到父的环境,这是一个用xybar上面创建的变量。确实,在这里我们找到了一个y变量,因此我们将值30放在该插槽中。
  5. bar函数被调用。再次,设置新的执行上下文(如上),将步骤1中的上下文作为其父范围(由实例化函数barin的词法位置确定-词法闭包)。现在,我们记录这三个感兴趣的表达式: foobar
    • x解析为x范围内的变量该变量foo仍具有值undefined
    • y解析为y范围内的变量该变量foo保存30我们刚刚分配的值
    • a.x解析为对象x属性,属性a保存20我们刚刚分配的值

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章