With块中的变量声明

时间:2017-04-17 20:39:01

标签: javascript scope lexical-scope

我在前言中说我知道使用with非常气馁,我也不打算使用它。我只是好奇学习它是如何工作的(我试图在javascript中找出范围)。

如果我有这样的代码:

function foo(obj) {
    with (obj) {
        b = 2;
    }
}

var o1 = {
    a: "something"
};

foo( o1 );
console.log(o1.b) // This outputs undefined (makes sense)
console.log(b) // This outputs 2 (makes sense)

但是,如果我将foo改为这样的话:

function foo(obj) {
    with (obj) {
        var b = 2; // I use var b instead of b
    }
}

当我将o1传递给foo时,o1再次没有属性b。为什么是这样?我认为使用var会在obj的范围内声明b,因此该属性将在o1内而不是在全局范围内创建。

2 个答案:

答案 0 :(得分:2)

var声明已被悬挂。所以你正在执行的是等同于

function foo(obj) {
    var b;
    with (obj) {
        b = 2;
    }
}

声明在with块内并不重要。 §9.2.12描述了评估函数体时会发生什么。在步骤11/12中,收集所有变量声明。 with语句只是“转发”其中的所有声明(see spec)。

答案 1 :(得分:1)

变量声明(使用var)不尊重块范围,而是hoisted到范围的顶部。就编译器/解释器而言,您的代码实际上是:

function foo(obj) {
    var b = undefined;
    with (obj) {
        b = 2;
    }
}