Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在JavaScript中,当局部变量被提升时,它是否在声明之前就在作用域中?_Javascript_Scope_Hoisting - Fatal编程技术网

在JavaScript中,当局部变量被提升时,它是否在声明之前就在作用域中?

在JavaScript中,当局部变量被提升时,它是否在声明之前就在作用域中?,javascript,scope,hoisting,Javascript,Scope,Hoisting,在书中,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

在书中,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
,而是
未定义的
,这意味着
b
是一个局部范围
b
,因此,
b
在本书的示例中确实已经存在


上述描述和概念正确吗?

的确,这本书的结论是错误的
var b
函数中的任意位置表示函数中的任意位置都存在
b
。这就是“提升”的含义。所有
var
function
声明都被提升到顶部,无论它们出现在范围内的何处。该值尚未分配。

关于代码:

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

b在声明之前还不在范围内

这是错误的
b
处于“范围内”(因为它是声明的,在执行任何代码之前创建的),但尚未分配值,因此
typeof b
返回
undefined
,测试失败

上述描述和概念正确吗

是的,差不多。一个更简单的证明是:

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.

var b
被提升到函数范围的顶部,因此函数后面的
b
引用本地
b
,而不考虑顺序。那么这本书的描述是错误的?“功能范围的顶部”是什么意思?(范围就是范围,范围没有顶部或底部)。你的意思是“提升到功能的顶部(好像它是第一行,并且在功能的局部范围内,无论它出现在功能内部的什么位置”?我不喜欢“提升”这个词,它推断声明被移到了某个东西的顶部,而这并不是实际发生的情况。在执行任何代码之前,所有声明都会被处理,所以这也是您应该考虑的。对范围的影响是副作用。但“最终效果”不是与“提升”完全相同吗?(即使这不是实际发生的情况)。这就是为什么一些程序员会“手动将它们全部提升到函数内容的开头”,这样就不会产生混淆。你说的“更多或更少”是什么意思?如果某一点不正确,你能指出吗?我说的“更多或更少”是因为“在范围内”是行话。严格来说,声明局部变量会在执行任何代码之前创建局部执行对象的属性。标识符解析将找到“局部”属性(变量)不要在作用域链上进一步搜索。没有提到的是,全局
b
不存在,直到分配给它的代码导致它被创建。最后,一旦创建为全局,它对于从同一全局上下文创建的每个执行上下文都“在作用域内”,即使它可能被“隐藏”通过作用域链其他部分中具有相同名称的变量。