ES6模块 - 为什么我可以在声明之前使用const?

时间:2018-01-29 18:31:29

标签: import ecmascript-6 export const es6-modules

我试过在这个确切的场景中寻找解释,却找不到任何东西。我有一个模块,如下所示(简化):

in1

显然,上面的const定义是悬挂的,但在函数中使用时应该是未定义的。我试图找到一个确切的解释,说明导入和使用此功能的原因。不应该抛出引用错误?我唯一能想到的是整个模块在调用此函数之前加载,但是完全是如何发生这种情况的呢?或者这个特定行为的解释在哪里?任何信息都会非常感激。

2 个答案:

答案 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

letconst的延迟初始化的这种行为通常被称为“时间死区”。

在一天结束时,只要变量已初始化并且在您访问变量时具有您关心的值,您的代码就可以了。您是否首先访问变量只取决于代码的嵌套。

答案 1 :(得分:0)

只有在执行了您提供的整个模块之后(这意味着在调用该函数时map已经被初始化),才能在该模块外部进行调用。

此观察基于以下事实:导入模块时,模块中的所有代码都将被执行。 要调用该函数,必须导入您提供的模块。

有关何时在导入时执行代码,请参见Does ES6 module importing execute the code inside the imported file?

相关问题