我试过在这个确切的场景中寻找解释,却找不到任何东西。我有一个模块,如下所示(简化):
in1
显然,上面的const定义是悬挂的,但在函数中使用时应该是未定义的。我试图找到一个确切的解释,说明导入和使用此功能的原因。不应该抛出引用错误?我唯一能想到的是整个模块在调用此函数之前加载,但是完全是如何发生这种情况的呢?或者这个特定行为的解释在哪里?任何信息都会非常感激。
答案 0 :(得分:0)
JS使用词法作用域,这意味着作用域被定义为代码嵌套结构的一部分。引用该范围内任何位置的变量名称的任何内容都可以尝试访问该值。实际的值取决于初始化值的时间,这是代码的运行时属性。
当人们在JS中谈论hoisting
时,他们所描述的这些事情并不是很清楚。在JS中,因为范围是基于词汇的,所以提升了给定变量的存在,因为它总是存在于该范围内。
范围中变量的实际初始化取决于声明变量的方式。
function foo(){}
声明已初始化,因此变量foo
将始终在函数体中可用,即使声明稍后出现也是如此。 e.g。
foo();
function foo(){}
完全有效。
var foo = 4;
提升初始化,但在声明执行之前,该值初始化为undefined
,例如
foo; // undefined
var foo = 4;
foo; // 4
let
/ const
仅在执行时执行初始化,并且尝试访问未初始化的变量将引发异常。
foo; // would throw because it is not initialized yet
let foo = 4;
foo; // 4
因此,将这些变为一起,变量的行为仅在运行时确定。对于您的代码示例,它取决于函数的调用时间。由于let foo = 4;
仅在运行时初始化foo
,如果首先调用该函数,它将失败,如果函数被调用,它将起作用。
function log(){
console.log(foo);
}
log(); // would throw because foo has not been initialized
let foo = 4;
log(); // would log 4
let
和const
的延迟初始化的这种行为通常被称为“时间死区”。
在一天结束时,只要变量已初始化并且在您访问变量时具有您关心的值,您的代码就可以了。您是否首先访问变量只取决于代码的嵌套。
答案 1 :(得分:0)
只有在执行了您提供的整个模块之后(这意味着在调用该函数时map已经被初始化),才能在该模块外部进行调用。
此观察基于以下事实:导入模块时,模块中的所有代码都将被执行。 要调用该函数,必须导入您提供的模块。
有关何时在导入时执行代码,请参见Does ES6 module importing execute the code inside the imported file?。