在尝试捕获操作过程中,“究竟”发生了什么事?

时间:2018-07-18 18:33:50

标签: javascript error-handling try-catch

  

如果您对问题的详细信息不感兴趣,可以直接跳至TL/DR


简短的序言:

我最近决定完全重新学习JavaScript。 这次不仅是如何运作的,而且还有它为什么运作的。一旦您还了解了编译器的工作方式以及所有其他细腻的细节,一切都会变得更加有意义,问题是有一个小的预构建表达式:

try.. catch

当它似乎违反了JS的所有词法和作用域规则时,我还无法确定它为什么起作用。


我没有得到的东西:

这不应该超出范围吗?

在这里,我们仅在两个级别的范围内工作。
try{ }内的范围和catch{ }内的范围。如果我们要说明这一点,它将看起来像这样:

enter image description here

现在,两个内部作用域应充当两个单独的作用域,而不应彼此冲突。考虑到这一点,** global的值如何返回到try {}块中,而应将其作为范围包含在自身中。

我什至尝试使用catch {}来查看是否能以某种方式捕获试图在块范围之外传递参数的异常,但即使那样.. nada仍能按预期工作:

  

从技术上讲,我在这里使用"use strict";创建了一个额外的范围,   不幸的是,如果没有   自我调用功能

function()

尽管(function(){ "use strict"; try { throw 'MadeUpError'; } catch(e) { console.log(e); } })();块与try {}发生冲突,但为什么catch {}块才能将参数传递给strict mode

当标识符(e)仅对其自己的作用域唯一时,似乎很不合逻辑。

此外,我什至无法从词汇上理解它。 catch块要求对抛出的异常不存在的索引(?)进行右侧查找。
从何处以及如何知道应该从何处检索异常


TL / DR:

回答这个问题的最简单方法可能是以编译器的伪语言来回答它,例如:

/*
    1. I arrived at try { } block
    2. Created a new Exception
    3. I stored Exception at (?)
    4. Exited try { }
    5. I looked up Exception from ...
*/

希望您能收到我冗长的文章。我知道这更多是一个理论问题,但是我想完全理解try..catch操作期间幕后发生的事情。

2 个答案:

答案 0 :(得分:2)

  • 我到达try {块并将其位置推到try {块堆栈中(到达}时会弹出)*

  • 我在块内执行代码

  • 我到达了throw whatever

  • 我将whatever评估为表达式(如果它是一个标识符,我会在当前范围内查找它)

  • 我将评估结果存储在一个临时内部变量中

  • 我从堆栈中查找最高的try { }并将其弹出

  • 我进入相关的catch(identifier) { }街区

  • 我在catch块的范围内创建了identifier,并将内部变量的值复制到其中

  • 我执行catch块

  • 我在catch块之后执行代码

(这非常简化,它甚至在async函数中变得更加复杂),您可以按ECMA规范的$ 13.15.7 / 8阅读全部内容。

  

这不应该超出范围吗?

抛出的东西根本不必成为try { }范围的一部分:

throw new Error();

它也可以只是表达式的一部分。但是,如果它属于以下范围:

const error = new Error();
throw error; // <- handed over to some internal engine logic

然后将其抛出将导致将其复制到范围之外(复制到某个内部变量中),该范围将停止存在(因为该块停止执行),并将其复制到一个新范围的新变量中: / p>

catch(err) { // <- the error suddenly appears from inside the engine here

所以会有两个带两个变量的作用域,但是它们具有相同的值。


** Spec将其定义为对块的递归评估,然后将在throw语句中结束直到到达Try块,但我认为使用堆栈更容易理解(该递归将是最后)。

答案 1 :(得分:0)

(function(){

"use strict";

    try {
          throw 'MadeUpError';
    }

    catch(e) {
        console.log(e);
    }

})();
  

try {}块如何能够将参数传递给catch {}   阻止,尽管事实与严格模式冲突?

将其视为一种if / else块。如果出现错误,则执行catch块中的内容。 catch块中将自动包含“ e”(错误对象),因为您当然想知道错误是什么。 Javscript只是将其放在堆栈上,并允许您自动引用它