javascript - 在 try catch 操作期间*究竟*发生了什么?

标签 javascript error-handling try-catch

Feel free to skip straight to TL/DR if you're not interested in details of the question


简短的序言:

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

try.. catch

而且我无法完全理解它为什么有效,当它似乎违反 JS 现有的所有词法和范围规则时。


我没有得到的东西:

它不应该打破范围吗?

这里我们只使用 2 个级别的范围。
try{ } 内的范围 catch{ } 内的范围和 global 范围。如果我们要说明这一点,它看起来像这样:

enter image description here

现在这两个内部作用域应该充当两个独立的作用域并且不会相互冲突。考虑到这一点,**为什么 try {} 的值返回到 catch {} block ,而它应该作为范围包含在自身中。

我什至尝试使用 "use strict"; 来查看我是否能以某种方式捕获试图在 block 范围之外传递参数的异常,但即便如此...... nada,仍按预期工作:

Technically I created an extra scope here with the function(), unfortunately it's impossible to use strict mode in jsfiddle without self-invoked function

(function(){
"use strict";

	try {
          throw 'MadeUpError';
	}

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

})();

为什么 try {} block 能够将参数传递给 catch {} block ,尽管它与 冲突>严格模式?

当标识符 (e) 应该只在它自己的范围内是唯一的时,这似乎很不合逻辑。

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


长话短说:

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

/*
    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 操作期间幕后发生的事情。

最佳答案

  • 我到达 try { block 并将其位置压入 try { block 的堆栈(当 } 已达到)*

  • 我执行 block 内的代码

  • 我到达了一个throw whatever

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

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

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

  • 我转到相关的 catch(identifier) { } block

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

  • 我执行 catch block

  • 我在 catch block 之后执行代码

(这非常简单,它甚至在 async 函数内部变得有点复杂),您可以在 ECMA 规范的 $13.15.7/8 处阅读整个故事。

Shouldn't it break the scope?

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

throw new Error();

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

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

然后抛出它会导致它被复制出作用域(进入某个内部变量),作用域将停止存在(因为 block 停止执行)并且它将被复制到新作用域的新变量中:

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

因此会有两个作用域和两个变量,但它们具有相同的值。


*规范将其定义为 block 的递归评估,然后将在 throw 语句处结束,直到到达 Try block ,但我认为使用堆栈更容易理解(它递归将在最后)。

关于javascript - 在 try catch 操作期间*究竟*发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51408832/

相关文章:

c++ - (定义一个宏来)方便OpenGL命令调试?

swift - 如何处理导致 "try?"的 Swift 的 "Result of try? is unused"?

r - 如何在 R 中使用 `tryCatch` 正确记录警告和错误?

sql-server - T-SQL TRY CATCH 的问题?

javascript - 让用户在 div/img 上画一条线(箭头)

javascript - clearRect 不清除 Canvas

javascript - 第一个单词用 <span> 换行,其余文本用另一个 <span> 换行,使用 Jquery 用 <br> 标记分隔

objective-c - Throwing 方法不能是@objc 协议(protocol)的成员,因为它返回类型为 'Bool' 的值

javascript - AngularJS - cordova android 上的意外 token "catch"

javascript - 使用 ajax 时 asp mvc 显示不更新