在JavaScript中,当一个局部变量被提升时,它是否在声明范围之前就在范围内?

时间:2013-02-21 08:03:26

标签: javascript scope hoisting

在书Secrets of the JavaScript Ninja中,p。 43 - 46,它有一些代码:

function assert(flag, msg) {
    if (!flag) {
        console.log("Assertion failed for: " + msg);
    }
}

function outer() {
    var a = 1;

    function inner() { }

    assert(typeof b === "number", "b is in scope");
    var b = 1;
}

outer();

结论是,由于断言失败,“b尚未在范围内,直到声明为止”。但我认为不是这样,因为首先,b已经具有本地范围,但只是它还不是“数字”。 b实际上已经是本地范围b,并且会影响任何全局范围b

例如:

var b = 123;

function foo() {
    b = 456;

    var b = 789;
}

foo();

console.log(b);   // prints out 123

因为它打印出123,所以我们可以看到,当执行第b = 456;行时,b已经是本地范围b。 (即使在作业之前它尚未初始化)。

此外,我们可以打印出来而不是分配给b

var b = 123;

function foo() {
    console.log(b);  // prints out undefined

    var b = 789;
}

foo();

console.log(b);     // prints out 123

再次,我们可以看到第一次打印输出不是123,而是undefined,这意味着b是本地范围b,因此{ {1}}实际上已经在本书的范例内了。

以上描述和概念是否正确?

2 个答案:

答案 0 :(得分:5)

确实,这本书的结论是错误的。函数内的var b 任何地方意味着b在函数内部任何位置存在。这就是“吊装”的意思。所有varfunction声明都会被提升到顶部,无论它们在作用域中出现在何处。尚未分配

答案 1 :(得分:2)

关于代码:

assert(typeof b === "number", "b is in scope");
var b = 1;

声明:

  

“b尚未在范围内,直到声明为”

错了。 b是'范围'(因为它已声明,它是在执行任何代码之前创建的)但尚未分配值,因此typeof b返回undefined并且测试失败。< / p>

  

以上描述和概念是否正确?

是的,或多或少。一个更简单的证据是:

function foo() {
  alert(b);
  var b = 5;
}

function bar() {
  alert(x);
  x = 5;
}

foo() // 'undefined' since b is "in scope" but hasn't been assigned a value yet

bar() // throws an error since x isn't "in scope" until the following line.