在JavaScript中,当局部变量被提升时,它是否在声明之前就在作用域中?
在书中,p。43-46,它有一些代码,如:在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
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
不存在,直到分配给它的代码导致它被创建。最后,一旦创建为全局,它对于从同一全局上下文创建的每个执行上下文都“在作用域内”,即使它可能被“隐藏”通过作用域链其他部分中具有相同名称的变量。