Javascript 何时才能确定let或const是否已初始化?

Javascript 何时才能确定let或const是否已初始化?,javascript,ecmascript-6,closures,let,scoping,Javascript,Ecmascript 6,Closures,Let,Scoping,Jason Orendorff在他的onlet和const中陈述了以下内容: 关键性能细节:在大多数情况下,您可以判断 声明是否已运行,而不仅仅是通过查看代码,因此 JavaScript引擎实际上不需要执行额外的检查 每次访问变量时,都要确保 初始化。然而,在闭包内部,有时并不清楚。在里面 在这些情况下,JavaScript引擎将执行运行时检查。这意味着 let可以比var慢一点 我决定试着找到一个例子,证明这一点是正确的,但却被难倒了 例如,让我们看看以下酷刑场景: function doSo

Jason Orendorff在他的on
let
const
中陈述了以下内容:

关键性能细节:在大多数情况下,您可以判断 声明是否已运行,而不仅仅是通过查看代码,因此 JavaScript引擎实际上不需要执行额外的检查 每次访问变量时,都要确保 初始化。然而,在闭包内部,有时并不清楚。在里面 在这些情况下,JavaScript引擎将执行运行时检查。这意味着
let
可以比
var
慢一点

我决定试着找到一个例子,证明这一点是正确的,但却被难倒了

例如,让我们看看以下酷刑场景:

function doSomethingDumb(q) {
    function crash() { ++x; }
    q.fn = crash;
    crash();
    let x;
    return crash;
}
即使在函数结束时返回闭包,也可以保证return语句永远不会执行,即使
x
被分配给
q
的一个成员(因此可能会逃逸)
x
永远不会被初始化,因此
crash
总是会崩溃


在什么情况下,不可能判断变量是否已初始化

把它放到一个只有在某些情况下才能满足的条件中:

function example() {
    if (Math.random() < 0.33) tryIt();
    const x = 5;
    if (Math.random() < 0.5) tryIt();
    function tryIt() {
        console.log(x);
    }
}
函数示例(){
if(Math.random()<0.33)tryIt();
常数x=5;
if(Math.random()<0.5)tryIt();
函数tryIt(){
控制台日志(x);
}
}

在本例中,我选择了一个随机变量,但它也可能取决于函数的输入参数。一般来说,访问变量的语句是否会在初始化之前执行是不可静态判断的,这是最重要的。您可以编写一个复杂的分析器,可以在许多情况下确定这一点,但在复杂度和分析器开销之间总是有一个折衷。

没有慢句柄或快句柄,即:命名值,无论是var、const还是let。也没有“无法确定”它们是否已初始化的情况。 此外,我们不需要初始化,它们只是被分配。由于它们的行为类似于“未声明的变量”,因此它们将在运行时被赋值,并精确地在其点声明处赋值


因此,如果发生停止错误,则仅在let声明上方一行发生。它仍将完全未申报。你只要看一下代码就知道了。

crash()
甚至不会执行,当你试图将
x
分配给
q.fn
时,它已经崩溃了。这应该是q.fn=crash。谢谢你抓住了。顺便说一句,你能把这篇文章和那句话联系起来吗?契约完成了。@Bekinbaja问题是“这里有一个例子,很清楚当访问时,
x
是否是初始化的;不清楚的情况是什么?”,我已经展示了一个例子,在这个例子中,它不是很容易看到,而且在每种情况下都无法确定。你可能想看看“声明”和“初始化”对
意味着什么。让
/
常量
.Hm,它们的行为与未声明的变量完全不同。是的,虽然解释器总是可以确定(测试)变量是否已经初始化,但我们讨论的是编译器优化,它确定这样的测试是否必要。这是不可判定的。条件\block\local作用域中varletconst的错误实现和错误行为在失败的查找后阻碍了查找原则,如:
function lookupDisabled(){const myval=1;console.log(myval);if(myval==1){/*console.log(myval);ReferenceError*/const myval=2;console.log(myval);if(myval==2){/*console.log(myval);ReferenceError*/const myval=3;console.log(myval);}console.log(myval);}return myval;}
其中myval的注释日志应该能够在外部范围中查找日志1。不,这既不是错误,也不是错误。请检查这是如何工作的。以及。任何违反直觉、出乎意料的错误行为;特别是那些违背给定语言的基本编程原则的,根据定义是错误的,通常被认为是错误的。这一条毫无理由地破坏了查找原则。这是一个过早的错误的在解析时进行的前瞻性包含优化(这可能会节省一些cpu周期),但仍然是一个bug。仅仅因为给定值的标识符正在等待声明,就不应该成为使其不可访问的理由,特别是当创建当前上下文的条件声明时!0