Files
AutoJs6/app/src/main/assets-app/docs/exceptions.html
2025-01-01 17:15:17 +08:00

1124 lines
52 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>异常 (Exceptions) | AutoJs6 文档 - 6.6.1</title>
<link rel="stylesheet" href="assets/fonts.css">
<link rel="stylesheet" href="assets/style.css">
<link rel="stylesheet" href="assets/sh.css">
<link rel="stylesheet" href="plugins/docsify-copy-code@2-styles.css">
<link rel="stylesheet" href="plugins/zoom-image-styles.css">
<link rel="canonical" href="https://nodejs.org/api/exceptions.html">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="user-scalable=no">
</head>
<body class="alt apidoc" id="api-section-exceptions">
<div id="content" class="clearfix">
<div id="column2" class="interior">
<div id="intro" class="interior">
<a href="/" title="返回首页">
AutoJs6
</a>
</div>
<ul>
<li><a class="nav-overview" href="overview.html">Overview - 综述</a></li>
<li><a class="nav-documentation" href="documentation.html">About - 关于文档</a></li>
<li><a class="nav-progress" href="progress.html">Progress - 文档部署进度</a></li>
<li><a class="nav-changelog" href="changelog.html">Changelog - 文档更新日志</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-manual" href="manual.html">Manual - AutoJs6 使用手册</a></li>
<li><a class="nav-qa" href="qa.html">Q &amp; A - 疑难解答</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-global" href="global.html">Global - 全局对象</a></li>
<li><a class="nav-automator" href="automator.html">Automator - 自动化</a></li>
<li><a class="nav-autojs" href="autojs.html">AutoJs6 - 本体应用</a></li>
<li><a class="nav-app" href="app.html">App - 通用应用</a></li>
<li><a class="nav-color" href="color.html">Color - 颜色</a></li>
<li><a class="nav-image" href="image.html">Image - 图像</a></li>
<li><a class="nav-ocr" href="ocr.html">OCR - 光学字符识别</a></li>
<li><a class="nav-barcode" href="barcode.html">Barcode - 条码</a></li>
<li><a class="nav-qrcode" href="qrcode.html">QR Code - 二维码</a></li>
<li><a class="nav-keys" href="keys.html">Keys - 按键</a></li>
<li><a class="nav-device" href="device.html">Device - 设备</a></li>
<li><a class="nav-storages" href="storages.html">Storage - 储存</a></li>
<li><a class="nav-files" href="files.html">File - 文件</a></li>
<li><a class="nav-engines" href="engines.html">Engine - 引擎</a></li>
<li><a class="nav-tasks" href="tasks.html">Task - 任务</a></li>
<li><a class="nav-modules" href="modules.html">Module - 模块</a></li>
<li><a class="nav-plugins" href="plugins.html">Plugins - 插件</a></li>
<li><a class="nav-toast" href="toast.html">Toast - 消息浮动框</a></li>
<li><a class="nav-notice" href="notice.html">Notice - 消息通知</a></li>
<li><a class="nav-console" href="console.html">Console - 控制台</a></li>
<li><a class="nav-shell" href="shell.html">Shell</a></li>
<li><a class="nav-shizuku" href="shizuku.html">Shizuku</a></li>
<li><a class="nav-media" href="media.html">Media - 多媒体</a></li>
<li><a class="nav-sensors" href="sensors.html">Sensor - 传感器</a></li>
<li><a class="nav-recorder" href="recorder.html">Recorder - 记录器</a></li>
<li><a class="nav-timers" href="timers.html">Timer - 定时器</a></li>
<li><a class="nav-threads" href="threads.html">Thread - 线程</a></li>
<li><a class="nav-continuation" href="continuation.html">Continuation - 协程</a></li>
<li><a class="nav-events" href="events.html">Event - 事件监听</a></li>
<li><a class="nav-dialogs" href="dialogs.html">Dialog - 对话框</a></li>
<li><a class="nav-floaty" href="floaty.html">Floaty - 悬浮窗</a></li>
<li><a class="nav-canvas" href="canvas.html">Canvas - 画布</a></li>
<li><a class="nav-ui" href="ui.html">UI - 用户界面</a></li>
<li><a class="nav-web" href="web.html">Web - 万维网</a></li>
<li><a class="nav-http" href="http.html">HTTP</a></li>
<li><a class="nav-base64" href="base64.html">Base64</a></li>
<li><a class="nav-crypto" href="crypto.html">Crypto - 密文</a></li>
<li><a class="nav-opencc" href="opencc.html">OpenCC - 中文转换</a></li>
<li><a class="nav-i18n" href="i18n.html">Internationalization - 国际化</a></li>
<li><a class="nav-s13n" href="s13n.html">Standardization - 标准化</a></li>
<li><a class="nav-e4x" href="e4x.html">E4X</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-uiSelectorType" href="uiSelectorType.html">UiSelector - 选择器</a></li>
<li><a class="nav-uiObjectType" href="uiObjectType.html">UiObject - 控件节点</a></li>
<li><a class="nav-uiObjectCollectionType" href="uiObjectCollectionType.html">UiObjectCollection - 控件集合</a></li>
<li><a class="nav-uiObjectActionsType" href="uiObjectActionsType.html">UiObjectActions - 控件节点行为</a></li>
<li><a class="nav-webSocketType" href="webSocketType.html">WebSocket</a></li>
<li><a class="nav-eventEmitterType" href="eventEmitterType.html">EventEmitter - 事件发射器</a></li>
<li><a class="nav-imageWrapperType" href="imageWrapperType.html">ImageWrapper - 包装图像类</a></li>
<li><a class="nav-appType" href="appType.html">App - 应用枚举类</a></li>
<li><a class="nav-colorType" href="colorType.html">Color - 颜色类</a></li>
<li><a class="nav-versionType" href="versionType.html">Version - 版本工具类</a></li>
<li><a class="nav-polyfill" href="polyfill.html">Polyfill - 代码填泥</a></li>
<li><a class="nav-arrayx" href="arrayx.html">Arrayx - Array 扩展</a></li>
<li><a class="nav-numberx" href="numberx.html">Numberx - Number 扩展</a></li>
<li><a class="nav-mathx" href="mathx.html">Mathx - Math 扩展</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-exceptions active" href="exceptions.html">Exceptions - 异常</a></li>
<li><a class="nav-intentType" href="intentType.html">Intent - 意图</a></li>
<li><a class="nav-runtime" href="runtime.html">Runtime - 运行时</a></li>
<li><a class="nav-context" href="context.html">Context - 上下文</a></li>
<li><a class="nav-activity" href="activity.html">Activity - 活动</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-scriptingJava" href="scriptingJava.html">Scripting Java - 脚本化 Java</a></li>
<li><a class="nav-apiLevel" href="apiLevel.html">Android API Level - 安卓 API 级别</a></li>
<li><a class="nav-colorTable" href="colorTable.html">Color Table - 颜色列表</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-glossaries" href="glossaries.html">Glossaries - 术语</a></li>
<li><a class="nav-httpHeaderGlossary" href="httpHeaderGlossary.html">HttpHeader - HTTP 标头</a></li>
<li><a class="nav-httpRequestMethodsGlossary" href="httpRequestMethodsGlossary.html">HttpRequestMethods - HTTP 请求方法</a></li>
<li><a class="nav-mimeTypeGlossary" href="mimeTypeGlossary.html">MimeType - MIME 类型</a></li>
<li><a class="nav-notificationChannelGlossary" href="notificationChannelGlossary.html">NotificationChannel - 通知渠道</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-dataTypes" href="dataTypes.html">Data Types - 数据类型</a></li>
<li><a class="nav-omniTypes" href="omniTypes.html">Omnipotent Types - 全能类型</a></li>
<li><a class="nav-storageType" href="storageType.html">Storage - 存储类</a></li>
<li><a class="nav-androidBundleType" href="androidBundleType.html">AndroidBundle</a></li>
<li><a class="nav-androidRectType" href="androidRectType.html">AndroidRect</a></li>
<li><a class="nav-cryptoCipherOptionsType" href="cryptoCipherOptionsType.html">CryptoCipherOptions</a></li>
<li><a class="nav-cryptoKeyType" href="cryptoKeyType.html">CryptoKey</a></li>
<li><a class="nav-cryptoKeyPairType" href="cryptoKeyPairType.html">CryptoKeyPair</a></li>
<li><a class="nav-consoleBuildOptionsType" href="consoleBuildOptionsType.html">ConsoleBuildOptions</a></li>
<li><a class="nav-httpRequestBuilderOptionsType" href="httpRequestBuilderOptionsType.html">HttpRequestBuilderOptions</a></li>
<li><a class="nav-httpRequestHeadersType" href="httpRequestHeadersType.html">HttpRequestHeaders</a></li>
<li><a class="nav-httpResponseBodyType" href="httpResponseBodyType.html">HttpResponseBody</a></li>
<li><a class="nav-httpResponseHeadersType" href="httpResponseHeadersType.html">HttpResponseHeaders</a></li>
<li><a class="nav-httpResponseType" href="httpResponseType.html">HttpResponse</a></li>
<li><a class="nav-injectableWebClientType" href="injectableWebClientType.html">InjectableWebClient</a></li>
<li><a class="nav-injectableWebViewType" href="injectableWebViewType.html">InjectableWebView</a></li>
<li><a class="nav-noticeOptionsType" href="noticeOptionsType.html">NoticeOptions</a></li>
<li><a class="nav-noticeChannelOptionsType" href="noticeChannelOptionsType.html">NoticeChannelOptions</a></li>
<li><a class="nav-noticePresetConfigurationType" href="noticePresetConfigurationType.html">NoticePresetConfiguration</a></li>
<li><a class="nav-noticeBuilderType" href="noticeBuilderType.html">NoticeBuilder</a></li>
<li><a class="nav-okhttp3HttpUrlType" href="okhttp3HttpUrlType.html">Okhttp3HttpUrl</a></li>
<li><a class="nav-ocrOptionsType" href="ocrOptionsType.html">OcrOptions</a></li>
<li><a class="nav-okhttp3RequestType" href="okhttp3RequestType.html">Okhttp3Request</a></li>
<li><a class="nav-opencvPointType" href="opencvPointType.html">OpenCVPoint</a></li>
<li><a class="nav-opencvRectType" href="opencvRectType.html">OpenCVRect</a></li>
<li><a class="nav-opencvSizeType" href="opencvSizeType.html">OpenCVSize</a></li>
<li><a class="nav-openCCConversionType" href="openCCConversionType.html">OpenCCConversion</a></li>
</ul>
<div class="line"></div>
<ul>
<li><a class="nav-http-project-autojs6-com" href="http://project.autojs6.com">GitHub - 应用项目地址</a></li>
<li><a class="nav-http-docs-project-autojs6-com" href="http://docs-project.autojs6.com">GitHub - 文档项目地址</a></li>
</ul>
</div>
<div id="column1" data-id="exceptions" class="interior">
<header>
<h1>AutoJs6 文档 - 6.6.1</h1>
<div id="gtoc">
<p class="index">
<a href="index.html" name="toc">索引</a> |
<a href="all.html">查看全部</a>
</p>
</div>
<hr>
</header>
<div id="toc">
<h2>目录</h2>
<ul>
<li><span class="stability_undefined"><a href="#exceptions_exceptions">异常 (Exceptions)</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions">错误类型</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_javascript">JavaScript</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_error">Error</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_rangeerror">RangeError</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_referenceerror">ReferenceError</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_syntaxerror">SyntaxError</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_typeerror">TypeError</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_urierror">URIError</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_internalerror">InternalError</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_evalerror">EvalError</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#exceptions_dom">DOM</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_java">Java</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_rhino">Rhino</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_1">自定义</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#exceptions_2">异常处理</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_throw">throw 语句</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_try_catch">try...catch 语句</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_catch">catch 块</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_finally">finally 块</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#exceptions_error_1">Error 对象</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_error_2">[@] Error</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_p_name">[p#] name</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_p_message">[p#] message</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_p_stack">[p#] stack</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_p_linenumber">[p#] lineNumber</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_p_filename">[p#] fileName</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_p_javaexception">[p#] javaException</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_p_rhinoexception">[p#] rhinoException</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_m_tostring">[m#] toString</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_tostring">toString()</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#exceptions_m_tosource">[m#] toSource</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_tosource">toSource()</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#exceptions_p_stacktracelimit">[p] stackTraceLimit</a></span></li>
<li><span class="stability_undefined"><a href="#exceptions_m_preparestacktrace">[m] prepareStackTrace</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_preparestacktrace_errorobj_stacktraces">prepareStackTrace(errorObj, stackTraces)</a></span></li>
</ul>
</li>
<li><span class="stability_undefined"><a href="#exceptions_m_capturestacktrace">[m] captureStackTrace</a></span><ul>
<li><span class="stability_undefined"><a href="#exceptions_capturestacktrace_errorobj_constructoropt">captureStackTrace(errorObj, constructorOpt)</a></span></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div id="apicontent">
<h1>异常 (Exceptions)<span><a class="mark" href="#exceptions_exceptions" id="exceptions_exceptions">#</a></span></h1>
<p>当运行时发生错误, 新创建的 Error 对象会被抛出.<br>除通用的 Error 构造器外, JavaScript 还有其它类型的错误构造器, 详见下述 <a href="#exceptions_javascript">JavaScript 错误类型</a> 小节.</p>
<blockquote>
<p>注: Java 有 Error (错误) 和 Exception (异常) 之分, 它们都扩展自 Throwable 类.<br>JavaScript 有 Error (错误) 全局对象, 以及一系列细分 Error 对象 (如 TypeError 等).<br>虽然 JavaScript 没有 Exception (异常) 对象, 但章节标题依然采用 &quot;异常&quot; (而非 &quot;错误&quot;).</p>
</blockquote>
<p><code>try...catch</code> 语句可以捕获并处理异常, 详见下述 <a href="#exceptions_trycatch_语句">异常处理</a> 小节.</p>
<p><code>catch {}</code> (即 <code>catch 块</code>) 中, <code>e</code> 对象可用于获取异常相关信息,<br>而 Rhino 引擎重新包装了 <code>e</code> 对象, 通过 <a href="#exceptions_p_javaexception"><code>e.javaException</code></a><a href="#exceptions_p_rhinoexception"><code>e.rhinoException</code></a> 可获取更多异常信息,<br>详见下述 <a href="#exceptions_catch_块">catch 块</a> 小节.</p>
<h1>错误类型<span><a class="mark" href="#exceptions" id="exceptions">#</a></span></h1>
<h2>JavaScript<span><a class="mark" href="#exceptions_javascript" id="exceptions_javascript">#</a></span></h2>
<p>以下内置错误类型在 Rhino 引擎中均得以实现, 在 AutoJs6 支持全局调用.<br>如需创建自定义错误类型, 参阅下述 <a href="#exceptions_自定义">自定义错误类型</a> 小节.</p>
<h3>Error<span><a class="mark" href="#exceptions_error" id="exceptions_error">#</a></span></h3>
<p>通用 Error 构造器.</p>
<p>内置错误类型 TypeError, RangeError 等均扩展自 Error 构造器.<br>例如, 如果一个对象是 TypeError 的实例, 则也一定是 Error 的实例.</p>
<p>Error 实例的属性及方法可参阅 <a href="#exceptions_error_对象">Error 对象</a> 章节.</p>
<pre><code class="lang-js">try {
android();
} catch (e) {
console.log(e instanceof TypeError); // true
console.log(e instanceof Error); // true
}
</code></pre>
<h3>RangeError<span><a class="mark" href="#exceptions_rangeerror" id="exceptions_rangeerror">#</a></span></h3>
<p>越界错误.</p>
<p>RangeError 实例代表了当一个值不在其所允许的范围或者集合中的错误.</p>
<pre><code class="lang-js">/* 创建或应用. */
const check = function (num) {
const MIN = 1;
const MAX = 500;
if (num &lt; MIN || num &gt; MAX) {
throw new RangeError(`Number ${num} must be between ${MIN} and ${MAX}.`);
}
};
try {
check(523);
} catch (e) {
if (e instanceof RangeError) {
console.error(&quot;发生越界错误.&quot;);
throw e;
}
}
/* 复现 (Array 构造器参数不合法). */
// RangeError: Inappropriate array length.
let a = Array(-1);
/* 复现 (Number 部分实例方法参数不合法). */
// RangeError: Precision -1 out of range.
let n = (23).toExponential(-1);
// RangeError: Precision -2 out of range.
let n = (23).toFixed(-2);
// RangeError: Precision -3 out of range.
let n = (23).toPrecision(-3);
</code></pre>
<h3>ReferenceError<span><a class="mark" href="#exceptions_referenceerror" id="exceptions_referenceerror">#</a></span></h3>
<p>引用错误.</p>
<p>ReferenceError 实例代表了当一个不存在或尚未初始化的变量被引用时发生的错误.</p>
<pre><code class="lang-js">/* 创建或应用. */
const f = function (num, options) {
if (typeof options === &#39;undefined&#39;) {
throw new ReferenceError(&quot;Invalid options.&quot;);
}
/* Other code... */
};
f(23);
/* 复现. */
// ReferenceError: a is not defined.
a;
</code></pre>
<h3>SyntaxError<span><a class="mark" href="#exceptions_syntaxerror" id="exceptions_syntaxerror">#</a></span></h3>
<p>语法错误.</p>
<p>SyntaxError 实例代表了当 Javascript 引擎发现 tokens 不合法或 token 顺序不合法时抛出的错误.</p>
<pre><code class="lang-badjs">/* 创建或应用. */
try {
eval(&quot;...&quot;);
} catch (e) {
if (e instanceof SyntaxError) {
console.error(&quot;发生语法错误, 位于 eval.&quot;);
throw e;
}
}
/* 复现. */
// Firefox 103.0 - SyntaxError: expected expression, got &#39;??&#39;.
// Node.js 17.3.0 - SyntaxError: Unexpected token &#39;??&#39;.
// AutoJs6 - syntax error.
??
</code></pre>
<blockquote>
<p>注: Rhino 内置了 token 解析器,<br>因此多数语法错误会被重新解析后再抛出,<br>而其他多数 JavaScript 引擎则直接抛出 SyntaxError.</p>
</blockquote>
<blockquote>
<p>Rhino 相关类或文件:<br><a href="https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/Parser.java">org.mozilla.javascript.Parser</a><br><a href="https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/TokenStream.java">org.mozilla.javascript.TokenStream</a><br><a href="https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/resources/Messages.properties">Messages.properties</a></p>
</blockquote>
<h3>TypeError<span><a class="mark" href="#exceptions_typeerror" id="exceptions_typeerror">#</a></span></h3>
<p>类型错误.</p>
<p>TypeError 实例代表了当一个值的类型为非预期类型时发生的错误.</p>
<pre><code class="lang-js">/* 创建或应用. */
try {
throw new TypeError(&#39;Hello&#39;, &quot;someFile.js&quot;, 10);
} catch (e) {
console.log(e instanceof TypeError); // true
console.log(e.message); // &quot;Hello&quot;
console.log(e.name); // &quot;TypeError&quot;
console.log(e.fileName); // &quot;someFile.js&quot;
console.log(e.lineNumber); // 10
}
/* 复现. */
// TypeError: Cannot call method &quot;f&quot; of null.
null.f();
// TypeError: java is not a function, it is object.
java();
// TypeError: day is not a function, it is string.
[].every(&quot;day&quot;);
</code></pre>
<h3>URIError<span><a class="mark" href="#exceptions_urierror" id="exceptions_urierror">#</a></span></h3>
<p>URI 错误.</p>
<p>URIError 实例代表了当以一种错误方式使用全局 URI 处理方法时产生的错误.</p>
<pre><code class="lang-js">/* 创建或应用. */
try {
throw new URIError(&#39;Hello&#39;, &#39;someFile.js&#39;, 10);
} catch (e) {
console.log(e instanceof URIError); // true
console.log(e.message); // &quot;Hello&quot;
console.log(e.name); // &quot;URIError&quot;
console.log(e.fileName); // &quot;someFile.js&quot;
console.log(e.lineNumber); // 10
}
/* 复现. */
// URIError: Malformed URI sequence.
decodeURIComponent(&#39;%&#39;);
</code></pre>
<h3>InternalError<span><a class="mark" href="#exceptions_internalerror" id="exceptions_internalerror">#</a></span></h3>
<p>内部错误.</p>
<p>InternalError 实例代表了出现在 JavaScript 引擎内部的错误.</p>
<pre><code class="lang-js">/* 创建或应用. */
try {
console.log(App.HELLO);
} catch (e) {
if (e instanceof InternalError) {
console.error(&quot;发生内部错误: 未知的预置 App.&quot;);
throw e;
}
}
/* 复现. */
// InternalError: Java method &quot;vibrate&quot; cannot be assigned to.
runtime.device.vibrate = 1;
</code></pre>
<h3>EvalError<span><a class="mark" href="#exceptions_evalerror" id="exceptions_evalerror">#</a></span></h3>
<p>Eval 错误.</p>
<p>EvalError 实例代表了一个关于 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval">eval</a> 方法的错误.</p>
<pre><code class="lang-js">/* 创建或应用. */
try {
throw new EvalError(&#39;Hello&#39;, &#39;someFile.js&#39;, 10);
} catch (e) {
console.log(e instanceof EvalError); // true
console.log(e.message); // &quot;Hello&quot;
console.log(e.name); // &quot;EvalError&quot;
console.log(e.fileName); // &quot;someFile.js&quot;
console.log(e.lineNumber); // 10
}
/* 复现. */
/* eval 抛出具体类型的错误, 而非 EvalError, 因此基本无法复现. */
// ReferenceError: &quot;hello&quot; is not defined.
eval(&quot;hello()&quot;);
/* 除非像上述 &quot;创建 EvalError&quot; 示例一样抛出错误, */
/* 或在 eval 中显式抛出 EvalError, */
/* 但这样做通常没有意义. */
// EvalError: test
eval(&quot;throw EvalError(&#39;test&#39;)&quot;);
</code></pre>
<blockquote>
<p>注: EvalError 不在当前 (2022/07) ECMAScript 规范中使用, 因此不会被运行时抛出.<br>但是对象本身仍然与规范的早期版本向后兼容.</p>
</blockquote>
<h2>DOM<span><a class="mark" href="#exceptions_dom" id="exceptions_dom">#</a></span></h2>
<p>DOMException 接口代表访问 Web API 属性或执行 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Introduction">DOM (文档对象模型)</a> 相关操作时发生的异常, 此异常通常是面对浏览器环境的.</p>
<p>当一个操作不可执行时, 如试图创建一个无效的 DOM 或通过一个不存在的节点作为参数节点操作方法, 会抛出 DOMException 异常:</p>
<pre><code class="lang-js">let node = document.getElementsByTagName(&#39;h1&#39;).item(0);
let refnode = node.nextSibling;
let newnode = document.createTextNode(&#39;test&#39;);
node.insertBefore(newnode, refnode); /* 抛出 DOMException 异常. */
</code></pre>
<p>DOMException 包含详细的名称分类, 如 [ &quot;NotFoundError&quot; / &quot;InvalidStateError&quot; / &quot;NoModificationAllowedError&quot; ] 等, 详情参阅 <a href="https://webidl.spec.whatwg.org/#idl-DOMException-error-names">Web IDL</a>.</p>
<h2>Java<span><a class="mark" href="#exceptions_java" id="exceptions_java">#</a></span></h2>
<p>Java 异常 (Exception) 类扩展自 Throwable 类, Exception 实例可使用 <a href="#exceptions_throw_语句">throw 关键字</a> 抛出.</p>
<p>Exception 可以被 <a href="#exceptions_trycatch_语句">try...catch 语句</a> 捕获并处理.</p>
<p>Error 类也扩展自 Throwable 类, 与 Exception 稍有不同, Error 往往是 Java 程序运行中不可预料且无法恢复的异常情况, 如 [ OutOfMemoryError / NoClassDefFoundError / StackOverflowError ] 等.</p>
<p>由 Java 方法抛出的原始异常, 指向 catch 块中异常对象的 <a href="#exceptions_p_javaexception">javaException</a> 属性.</p>
<p>常见的 Java 异常:</p>
<pre><code class="lang-text">Exception
├─ RuntimeException
│ │
│ ├─ NullPointerException
│ │
│ ├─ IndexOutOfBoundsException
│ │
│ ├─ SecurityException
│ │
│ └─ IllegalArgumentException
│ │
│ └─ NumberFormatException
├─ IOException
│ │
│ ├─ UnsupportedCharsetException
│ │
│ ├─ FileNotFoundException
│ │
│ └─ SocketException
├─ ParseException
├─ GeneralSecurityException
├─ SQLException
└─ TimeoutException
</code></pre>
<blockquote>
<p>参阅: <a href="https://www.liaoxuefeng.com/wiki/1252599548343744/1264737765214592">廖雪峰</a> / <a href="https://www.geeksforgeeks.org/errors-v-s-exceptions-in-java/">GeeksForGeeks </a></p>
</blockquote>
<h2>Rhino<span><a class="mark" href="#exceptions_rhino" id="exceptions_rhino">#</a></span></h2>
<p>Rhino 异常可以视为特殊的 <a href="#exceptions_java">Java 异常</a>, 由 Rhino <a href="runtime.html">运行时 (Runtime)</a> 包装为对象, 指向 catch 块中异常对象的 <a href="#exceptions_p_rhinoexception">rhinoException</a> 属性. </p>
<h2>自定义<span><a class="mark" href="#exceptions_1" id="exceptions_1">#</a></span></h2>
<p>本小节列举了几种自定义错误类型的方法.</p>
<ul>
<li>借助标准内置对象 Error:</li>
</ul>
<pre><code class="lang-js">function InvalidFruitError(msg) {
Error.call(this);
this.message = `Name of &quot;${msg}&quot; must end with &quot;Fruit&quot;`;
this.name = this.constructor.name;
}
InvalidFruitError.prototype = Object.create(Error.prototype, {
constructor: { value: InvalidFruitError },
});
function ensureFruitName(name) {
if (!name.endsWith(&quot;Fruit&quot;)) {
throw new InvalidFruitError(name);
}
}
// InvalidFruitError: Name of &quot;coconut&quot; must end with &quot;Fruit&quot;...
[ &quot;appleFruit&quot;, &quot;bananaFruit&quot;, &quot;coconut&quot; ].forEach(ensureFruitName);
</code></pre>
<ul>
<li>模拟标准内置对象 Error 的行为:</li>
</ul>
<pre><code class="lang-js">function InvalidFruitError(msg) {
this.message = `Name of &quot;${msg}&quot; must end with &quot;Fruit&quot;`;
this.name = this.constructor.name;
this.toString = () =&gt; `${this.name}: ${this.message}`;
}
function ensureFruitName(name) {
if (!name.endsWith(&quot;Fruit&quot;)) {
throw new InvalidFruitError(name);
}
}
// InvalidFruitError: Name of &quot;coconut&quot; must end with &quot;Fruit&quot;...
[ &quot;appleFruit&quot;, &quot;bananaFruit&quot;, &quot;coconut&quot; ].forEach(ensureFruitName);
</code></pre>
<ul>
<li>摘录自 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error">MDN</a> 的示例:</li>
</ul>
<pre><code class="lang-js">function CustomError(foo, message, fileName, lineNumber) {
var instance = new Error(message, fileName, lineNumber);
instance.foo = foo;
Object.setPrototypeOf(instance, CustomError.prototype);
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, CustomError);
}
return instance;
}
Object.setPrototypeOf(CustomError.prototype, Error.prototype);
Object.setPrototypeOf(CustomError, Error);
CustomError.prototype.name = &#39;CustomError&#39;;
try {
throw new CustomError(&#39;baz&#39;, &#39;bazMessage&#39;);
} catch (e) {
console.error(e.name); // CustomError
console.error(e.foo); // baz
console.error(e.message); // bazMessage
}
</code></pre>
<h1>异常处理<span><a class="mark" href="#exceptions_2" id="exceptions_2">#</a></span></h1>
<h2>throw 语句<span><a class="mark" href="#exceptions_throw" id="exceptions_throw">#</a></span></h2>
<p>使用 throw 语句抛出一个异常.<br>此异常可以是一个含有值的表达式, 包括 [ 数字 / 字符串 / 布尔 / 对象 ] 等多种类型.</p>
<p>不同语言的语法存在差异:</p>
<pre><code class="lang-java">/* Java. */
/* new 不可省略. */
throw new Exception(&quot;foo&quot;);
</code></pre>
<pre><code class="lang-kotlin">/* Kotlin. */
/* Kotlin 语言无 new 关键字. */
throw Exception(&quot;foo&quot;);
</code></pre>
<pre><code class="lang-js">/* JavaScript. */
/* Error 实例. */
throw new Error(&quot;foo&quot;);
/* Error 实例 (new 关键字省略). */
throw Error(&quot;foo&quot;);
/* 数字或字符串等表达式. */
throw &quot;foo&quot;; /* 合法. */
throw 23; /* 合法. */
throw true; /* 合法. */
/* 对象. */
throw {
name: &quot;CustomError&quot;,
message: &quot;test&quot;,
__proto__: Error.prototype,
};
/* 自定义 &quot;&quot; 的实例. */
function TestError(msg) {
this.message = msg;
this.name = this.constructor.name;
this.toString = () =&gt; `${this.name}: ${this.message}`;
}
throw new TestError(&quot;foo&quot;); /* new 关键字不可省略. */
</code></pre>
<h2>try...catch 语句<span><a class="mark" href="#exceptions_try_catch" id="exceptions_try_catch">#</a></span></h2>
<p>try...catch 语句标记一块待尝试的语句, 若语句出现异常 (包括主动使用 throw 语句抛出的异常), 该异常会被 try...catch 语句捕获:</p>
<pre><code class="lang-js">try {
throw new java.lang.RuntimeException(&quot;hello&quot;);
} catch (e) {
console.log(e.message); // &quot;hello&quot;
}
</code></pre>
<p>try...catch 语句必须有 try 代码块, 最多 1 个 catch 代码块 (catch 代码块省略时, 则必须存在 finally 代码块).</p>
<h2>catch 块<span><a class="mark" href="#exceptions_catch" id="exceptions_catch">#</a></span></h2>
<p>又名 &quot;捕捉块&quot;.</p>
<p>使用 catch 块处理在 try 代码块中产生的异常.<br>catch 块中的语句只有 try 代码块中抛出异常时才会执行.</p>
<pre><code class="lang-js">try {
0 === 1;
} catch (e) {
/* 不会执行, 因为 try 块中无异常. */
console.log(e.message);
}
</code></pre>
<p>catch 块中的异常信息对象 (通常用 e 或 ex 表示) 包含了异常的基本信息, 如 [ message / name / javaException / stack ] 等, 详见 <a href="#exceptions_error 对象">Error 对象</a> 章节.</p>
<p>Rhino 内置的 token 解析器可以解析像 Java 语言一样的多 catch 语句:</p>
<pre><code class="lang-badjs">function classForName(name) {
try {
return java.lang.Class.forName(name);
} catch (e if e.javaException instanceof java.lang.ClassNotFoundException) {
print(`Class ${name} not found`);
} catch (e if e.javaException instanceof java.lang.NullPointerException) {
print(&quot;Class name is null&quot;);
}
}
classForName(&quot;NonExistingClass&quot;); // Class NonExistingClass not found
classForName(null); // Class name is null
</code></pre>
<p>上述示例代码在 AutoJs6 可正常运行并返回预期结果, 但不符合 ECMAScript 语法, 且暂未发现任何可以解析此语法的 IDE, 使用后会造成 IDE 报错并在格式化代码时出现排版异常.</p>
<p>使用传统的单 catch 块语句可能会是更好的选择:</p>
<pre><code class="lang-js">try {
return java.lang.Class.forName(name);
} catch (e) {
if (e.javaException instanceof java.lang.ClassNotFoundException) {
print(`Class ${name} not found`);
} else if (e.javaException instanceof java.lang.NullPointerException) {
print(&quot;Class name is null&quot;);
}
}
</code></pre>
<h2>finally 块<span><a class="mark" href="#exceptions_finally" id="exceptions_finally">#</a></span></h2>
<p>finally 块中的语句无论 try 代码块是否抛出异常都会执行.</p>
<pre><code class="lang-js">try {
/* 打开并写入文件, 此处可能出现异常. */
} catch (e) {
/* 处理异常. */
} finally {
/* 关闭文件, 释放资源. */
}
</code></pre>
<p>finally 块存在时, catch 块可省略:</p>
<pre><code class="lang-js">try {
/* 打开并写入文件, 此处可能出现异常. */
} finally {
/* 关闭文件, 释放资源, 然后将异常重新抛出 (因为没有 catch 块捕获异常). */
}
</code></pre>
<p>如果 finally 块有返回值, 该值会是整个 try...catch...finally 流程的返回值, 而不论在 try 和 catch 块中语句的返回值:</p>
<pre><code class="lang-js">function f() {
try {
console.log(0);
throw &quot;error&quot;;
} catch (e) {
console.log(1);
return true; /* return 语句被暂时搁置, 直至 finally 块语句全部执行完成. */
console.log(2); /* 不可达. */
} finally {
console.log(3);
return false; /* 覆盖上一个 return 语句. */
console.log(4); /* 不可达. */
}
/* `return false` 已执行. */
console.log(5); /* 不可达. */
}
let res = f(); // 控制台打印 0, 1, 3
console.log(res); // false
</code></pre>
<h1>Error 对象<span><a class="mark" href="#exceptions_error_1" id="exceptions_error_1">#</a></span></h1>
<p>Error 对象是一个 JavaScript 构造函数, 它的实例通常由 <a href="#exceptions_catch_块">catch 块</a> 中的参数引用, 或通过 new 关键字产生相应的 Error 实例对象:</p>
<pre><code class="lang-js">try {
let err = new Error(&quot;test&quot;);
console.log(err instanceof Error); // true
throw err;
} catch (e) {
console.log(e instanceof Error); // true
}
</code></pre>
<p>对于 AutoJs6, catch 块中的引用对象 (通常用 e 或 ex 表示) 还由 Rhino 引擎额外封装了 <a href="#exceptions_p_javaexception">javaException</a><a href="#exceptions_p_rhinoexception">rhinoException</a> 两个对象.</p>
<hr>
<p style="font: bold 2em sans-serif; color: #FF7043">Error</p>
<hr>
<h2>[@] Error<span><a class="mark" href="#exceptions_error_2" id="exceptions_error_2">#</a></span></h2>
<h2>[p#] name<span><a class="mark" href="#exceptions_p_name" id="exceptions_p_name">#</a></span></h2>
<div class="signature"><ul>
<li>{ <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> }</li>
</ul>
</div><p>表示 Error 类型的名称, 初始值为 &quot;Error&quot;.</p>
<pre><code class="lang-js">console.log(new SyntaxError(&#39;hello&#39;).name); // &quot;SyntaxError&quot;
try {
throw TypeError(&#39;world&#39;);
} catch (e) {
console.log(e.name); // &quot;TypeError&quot;
}
</code></pre>
<h2>[p#] message<span><a class="mark" href="#exceptions_p_message" id="exceptions_p_message">#</a></span></h2>
<div class="signature"><ul>
<li>{ <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> }</li>
</ul>
</div><p>错误相关信息的描述.</p>
<pre><code class="lang-js">console.log(new SyntaxError(&#39;hello&#39;).name); // &quot;hello&quot;
try {
Math.random().toFixed(-1);
} catch (e) {
console.log(e.message); // &quot;精度 -1 超出范围.&quot;
}
</code></pre>
<h2>[p#] stack<span><a class="mark" href="#exceptions_p_stack" id="exceptions_p_stack">#</a></span></h2>
<div class="signature"><ul>
<li>{ <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> | <span class="type"><a href="dataTypes.html#datatypes_any">any</a></span> }</li>
</ul>
</div><p>stack 属性描述了 Error 对象的 <a href="https://zh.wikipedia.org/wiki/%E6%A0%88%E8%BF%BD%E8%B8%AA">栈追踪 (Stack Trace)</a> 信息.</p>
<p>栈追踪描述了程序运行过程中某个时间点上的活跃栈帧信息.<br>用户在日志中可以查看程序出错时的栈追踪信息, 用以自行排查代码异常或将栈追踪信息反馈给开发者.</p>
<pre><code class="lang-js">try {
!function test() {
throw Error(&#39;hello&#39;);
}();
} catch (e) {
/* 打印栈追踪信息. */
console.log(e.stack);
}
</code></pre>
<p>一个已格式化的栈追踪信息示例:</p>
<pre><code class="lang-text">ReferenceError: FAIL is not defined
at Constraint.execute (deltablue.js:525:2)
at Constraint.recalculate (deltablue.js:424:21)
at Planner.addPropagate (deltablue.js:701:6)
at Constraint.satisfy (deltablue.js:184:15)
at Planner.incrementalAdd (deltablue.js:591:21)
at Constraint.addConstraint (deltablue.js:162:10)
at Constraint.BinaryConstraint (deltablue.js:346:7)
at Constraint.EqualityConstraint (deltablue.js:515:38)
at chainTest (deltablue.js:807:6)
at deltaBlue (deltablue.js:879:2)
</code></pre>
<p>栈追踪的信息量由栈帧数量体现, 通过 <a href="#exceptions_p_stacktracelimit">Error.stackTraceLimit</a> 可设置栈帧数量.<br>栈追踪信息可通过 <a href="#exceptions_m_capturestacktrace">Error.captureStackTrace</a> 附加到一个 JavaScript 对象 (如 obj) 上, 通过访问 obj.stack 可随时查看栈追踪信息.<br><a href="#exceptions_m_preparestacktrace">Error.prepareStackTrace</a> 还可以自定义栈追踪信息的输出格式.</p>
<p>stack 属性默认返回 string 类型, 如果设置了 prepareStackTrace 格式函数, 则 stack 类型将与格式函数的返回值类型一致:</p>
<pre><code class="lang-js">Error.prepareStackTrace = function (e, frames) {
return frames.reduce((a, b) =&gt; a.concat([ b.getFunctionName() ]), []);
};
try {
!function test() {
throw Error(&#39;hello&#39;);
}();
} catch (e) {
/* 此时 stack 是一个数组. */
console.log(Array.isArray(e.stack)); // true
}
</code></pre>
<h2>[p#] lineNumber<span><a class="mark" href="#exceptions_p_linenumber" id="exceptions_p_linenumber">#</a></span></h2>
<div class="signature"><ul>
<li>{ <span class="type"><a href="dataTypes.html#datatypes_number">number</a></span> }</li>
</ul>
</div><p>表示抛出异常的代码在源文件中的行号.</p>
<pre><code class="lang-js">try {
throw Error(&quot;hello&quot;);
} catch (e) {
console.log(e.lineNumber); /* e.g. 5 */
}
</code></pre>
<h2>[p#] fileName<span><a class="mark" href="#exceptions_p_filename" id="exceptions_p_filename">#</a></span></h2>
<div class="signature"><ul>
<li>{ <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> }</li>
</ul>
</div><p>表示抛出异常的代码所在源文件的文件路径.</p>
<pre><code class="lang-js">try {
throw Error(&quot;hello&quot;);
} catch (e) {
console.log(e.fileName); /* e.g. &quot;/storage/emulated/0/Scripts/test.js&quot; */
}
</code></pre>
<h2>[p#] javaException<span><a class="mark" href="#exceptions_p_javaexception" id="exceptions_p_javaexception">#</a></span></h2>
<div class="signature"><ul>
<li>{ <span class="type"><a href="#exceptions_java">java.lang.Exception</a></span> }</li>
</ul>
</div><p>由 Java 方法抛出的原始异常.</p>
<pre><code class="lang-js">try {
/* 一些其他代码, 可能会抛出异常. */
/* ... */
/* 启动一个不存在的 Activity. */
app.startActivity({});
} catch (e) {
// &#39;[JavaException: android.content.ActivityNotFoundException: No Activity found to handle Intent { flg=0x10000000 }]&#39;
console.log(e);
console.log(e.javaException !== undefined); // true
/* 借助 e.javaException 类型处理不同的异常. */
if (e.javaException instanceof org.json.JSONException) {
console.error(&#39;JSON 解析错误&#39;);
throw (e);
}
if (e.javaException instanceof android.content.ActivityNotFoundException) {
console.error(&#39;指定的 Activity 不存在&#39;);
throw (e);
}
if (e.javaException instanceof ScriptInterruptedException) {
/* 忽略错误, 直接退出. */
exit();
}
if (e.javaException instanceof java.lang.RuntimeException) {
/* ... */
throw (e);
}
/* ... */
}
</code></pre>
<h2>[p#] rhinoException<span><a class="mark" href="#exceptions_p_rhinoexception" id="exceptions_p_rhinoexception">#</a></span></h2>
<div class="signature"><ul>
<li>{ <span class="type"><a href="#exceptions_java">java.lang.Exception</a></span> }</li>
</ul>
</div><p>由 Rhino 运行时 (Runtime) 包装的异常对象.</p>
<pre><code class="lang-js">try {
f();
} catch (e) {
// &#39;[ReferenceError: &quot;f&quot; is not defined.]&#39;
console.log(e);
/* e 是 ReferenceError 类型. */
console.log(e instanceof ReferenceError); // true
/* 同时也是 Error 类型. */
console.log(e instanceof Error); // true
/* 对象 e 是 Error 类型, 为 JavaScript 异常. */
/* 但 e.rhinoException 是 java.lang.Exception 类型, 为 Java 异常. */
console.log(e.rhinoException instanceof java.lang.Exception); // true
console.log(e.rhinoException instanceof org.mozilla.javascript.EcmaError); // true
console.log(e.rhinoException instanceof Error); // false
/* 因为 try 代码块没有触发 Java 异常, 因此 e.javaException 是 undefined. */
console.log(e.javaException); // undefined
}
</code></pre>
<h2>[m#] toString<span><a class="mark" href="#exceptions_m_tostring" id="exceptions_m_tostring">#</a></span></h2>
<h3>toString()<span><a class="mark" href="#exceptions_tostring" id="exceptions_tostring">#</a></span></h3>
<div class="signature"><ul>
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> }</li>
</ul>
</div><p>返回一个表示指定 Error 对象的字符串.</p>
<pre><code class="lang-js">let errA = new Error(&#39;hello&#39;);
console.log(errA.toString()); // &quot;Error: hello&quot;
let errB = new TypeError(&#39;world&#39;);
console.log(errB.toString()); // &quot;TypeError: world&quot;
errB.name = &#39;Banana&#39;;
console.log(errB.toString()); // &quot;Banana: world&quot;
errB.message = &quot;yellow&quot;;
console.log(errB.toString()); // &quot;Banana: yellow&quot;
</code></pre>
<h2>[m#] toSource<span><a class="mark" href="#exceptions_m_tosource" id="exceptions_m_tosource">#</a></span></h2>
<h3>toSource()<span><a class="mark" href="#exceptions_tosource" id="exceptions_tosource">#</a></span></h3>
<div class="signature"><ul>
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> }</li>
</ul>
</div><p>返回表示 Error 对象源代码的字符串.</p>
<pre><code class="lang-js">let err = new Error(&#39;hello&#39;);
console.log(err.toSource()); // (new Error(&quot;hello&quot;, &quot;&quot;))
try {
Math.random().toFixed(-1);
} catch (e) {
console.log(e.toSource()); // (new RangeError(&quot;\u7cbe\u5ea6 -1 \u8d85\u51fa\u8303\u56f4.&quot;, &quot;\u8fdc\u7a0b$Untitled-52js&quot;, 3))
throw eval(e.toSource()); /* 可供 eval 作为参数接收. */
}
</code></pre>
<h2>[p] stackTraceLimit<span><a class="mark" href="#exceptions_p_stacktracelimit" id="exceptions_p_stacktracelimit">#</a></span></h2>
<div class="signature"><ul>
<li>[ <code>Infinity</code> ] { <span class="type"><a href="dataTypes.html#datatypes_number">number</a></span> }</li>
</ul>
</div><p>设置或读取收集的栈追踪信息的栈帧数量.</p>
<blockquote>
<p>注: 该属性虽以 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#%E6%8F%8F%E8%BF%B0">数据描述符</a> 描述, 但通常以 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#%E6%8F%8F%E8%BF%B0">存取描述符</a> 方式使用, 且 setter 更具有实际意义.</p>
</blockquote>
<p>栈帧默认值为 Infinity, 即无数量限制:</p>
<pre><code class="lang-js">console.log(Error.stackTraceLimit); // Infinity
</code></pre>
<p>设置一个数量限制:</p>
<pre><code class="lang-js">Error.stackTraceLimit = 23;
console.log(Error.stackTraceLimit); // 23
</code></pre>
<p>恢复默认的数量限制值 (Infinity) 有多种方式:</p>
<pre><code class="lang-js">/* 直接设置 Infinity. */
Error.stackTraceLimit = Infinity;
/* 设置 NaN. */
Error.stackTraceLimit = NaN;
/* 设置负数. */
Error.stackTraceLimit = -1;
/* 设置无法转换为非 NaN 的 number 类型. */
Error.stackTraceLimit = &quot;hello&quot;;
</code></pre>
<p>注意与 0 的区分, 将数量限制设置为 0 表示不显示栈追踪信息, 即禁用栈追踪收集.</p>
<pre><code class="lang-js">let infoA = {};
let infoB = {};
try {
throw Error(&quot;hello&quot;);
} catch (e) {
Error.captureStackTrace(infoA);
Error.stackTraceLimit = 0;
Error.captureStackTrace(infoB);
console.log(infoA.stack); /* 打印栈追踪信息. */
console.log(infoB.stack); /* 打印空字符串. */
Error.stackTraceLimit = Infinity;
Error.captureStackTrace(infoB);
console.log(infoB.stack); /* 打印栈追踪信息. */
}
</code></pre>
<blockquote>
<p>参阅: <a href="https://v8.dev/docs/stack-trace-api">V8 Dev</a></p>
</blockquote>
<h2>[m] prepareStackTrace<span><a class="mark" href="#exceptions_m_preparestacktrace" id="exceptions_m_preparestacktrace">#</a></span></h2>
<p>用于自定义栈追踪信息格式, 该属性以函数形式发挥作用, 因此文档称之为 &quot;格式函数&quot;.</p>
<blockquote>
<p>注: 该属性虽以 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#%E6%8F%8F%E8%BF%B0">数据描述符</a> 描述, 但通常以 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#%E6%8F%8F%E8%BF%B0">存取描述符</a> 方式使用, 且 setter 更具有实际意义.</p>
</blockquote>
<p>格式函数默认值为 undefined, 即使用默认格式输出栈追踪信息:</p>
<pre><code class="lang-js">console.log(Error.prepareStackTrace); // undefined
</code></pre>
<p>设置自定义格式函数:</p>
<pre><code class="lang-js">Error.prepareStackTrace = function (e, frames) {
/* ... */
};
</code></pre>
<p>恢复默认的格式函数:</p>
<pre><code class="lang-js">/* 直接设置 null 或 undefined. */
Error.prepareStackTrace = undefined;
/* 除函数, null 和 undefined 外, 赋值其他类型的操作将被忽略, 不会有任何效果. */
Error.prepareStackTrace = &quot;hello&quot;; /* 无任何效果. */
</code></pre>
<blockquote>
<p>参阅: <a href="https://v8.dev/docs/stack-trace-api">V8 Dev</a></p>
</blockquote>
<h3>prepareStackTrace(errorObj, stackTraces)<span><a class="mark" href="#exceptions_preparestacktrace_errorobj_stacktraces" id="exceptions_preparestacktrace_errorobj_stacktraces">#</a></span></h3>
<div class="signature"><ul>
<li><strong>errorObj</strong> { <span class="type"><a href="#exceptions_error 对象">Error</a></span> } - 异常对象的引用</li>
<li><strong>stackTraces</strong> { <span class="type"><a href="https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_globals_d_.nodejs.callsite.html">NodeJS.CallSite</a><a href="dataTypes.html#datatypes_array">[]</a></span> } - 栈追踪数组 (栈帧组)</li>
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_any">any</a></span> }</li>
</ul>
</div><p>设置或查看用于自定义栈追踪信息的格式函数.</p>
<pre><code class="lang-js">Error.prepareStackTrace = function (e, frames) {
/* ... */
};
</code></pre>
<p>上述示例中的 frames (以及方法签名中的 stackTraces) 表示栈帧组, 每一个栈帧都是 <a href="https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_globals_d_.nodejs.callsite.html">NodeJS.CallSite</a> 类型.</p>
<p>下面列出了部分栈帧可用的属性或方法:</p>
<ul>
<li><code>[m#]</code> getColumnNumber</li>
<li><code>[m#]</code> getEvalOrigin</li>
<li><code>[m#]</code> getFileName</li>
<li><code>[m#]</code> getFunction</li>
<li><code>[m#]</code> getFunctionName</li>
<li><code>[m#]</code> getLineNumber</li>
<li><code>[m#]</code> getMethodName</li>
<li><code>[m#]</code> getThis</li>
<li><code>[m#]</code> getTypeName</li>
<li><code>[m#]</code> isConstructor</li>
<li><code>[m#]</code> isEval</li>
<li><code>[m#]</code> isNative</li>
<li><code>[m#]</code> isToplevel</li>
</ul>
<p>格式函数的返回值决定了 stack 属性的类型值.</p>
<pre><code class="lang-js">/* 格式函数返回值为 string 类型. */
Error.prepareStackTrace = function (e, frames) {
return frames.map(f =&gt; `${f.getFunctionName()}: ${f.getLineNumber()}`).join(&#39;\n&#39;);
};
try {
!function test() {
throw Error(&#39;hello&#39;);
}();
} catch (e) {
/* 与格式函数返回值同为 string 类型. */
console.log(e.stack);
}
</code></pre>
<h2>[m] captureStackTrace<span><a class="mark" href="#exceptions_m_capturestacktrace" id="exceptions_m_capturestacktrace">#</a></span></h2>
<p>附加 stack 属性 (栈追踪信息) 到任意对象上.</p>
<blockquote>
<p>参阅: <a href="https://v8.dev/docs/stack-trace-api">V8 Dev</a></p>
</blockquote>
<h3>captureStackTrace(errorObj, constructorOpt)<span><a class="mark" href="#exceptions_capturestacktrace_errorobj_constructoropt" id="exceptions_capturestacktrace_errorobj_constructoropt">#</a></span></h3>
<div class="signature"><ul>
<li><strong>errorObj</strong> { <span class="type"><a href="dataTypes.html#datatypes_object">object</a></span> } - 用于附加 stack 属性的任意对象</li>
<li><strong>constructorOpt</strong> { <span class="type"><a href="dataTypes.html#datatypes_function">Function</a></span> } - 用于在栈追踪信息中触发隐藏的函数</li>
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
</ul>
</div><p>附加 stack 属性 (栈追踪信息) 到任意对象上, 并支持在栈追踪信息中隐藏以指定的调用函数为起点的栈帧信息.</p>
<pre><code class="lang-js">let info = {};
try {
function a() {
Error.captureStackTrace(info);
return (0.5).toFixed(-1);
}
function b() {
a();
}
!function c() {
b();
}();
} catch (e) {
/* info 对象被附加了 stack 属性. */
/* stack 信息中包含函数 a, b, c 的栈帧信息, 顺序为 a (栈顶) -&gt; b -&gt; c (栈底). */
console.log(info.stack);
}
</code></pre>
<p>部分信息对于用户或开发者可能没有参考意义, 此时可使用 constructorOpt 参数隐藏部分栈帧信息:</p>
<pre><code class="lang-js">let info = {};
try {
function a() {
/* b (含) 及其栈顶方向的所有函数调用均将隐藏. */
Error.captureStackTrace(info, b);
return (0.5).toFixed(-1);
}
function b() {
a();
}
!function c() {
b();
}();
} catch (e) {
/* stack 信息中 b 和 a 被隐藏, 仅 c 被保留. */
console.log(info.stack);
}
</code></pre>
<p>上述示例中的 <code>b</code> 如果替换为 <code>c</code>, 则所有栈帧全部被隐藏, <code>info.stack</code> 将返回 <code>undefined</code> (即 stack 没有被附加到 info 对象上):</p>
<pre><code class="lang-js">let info = {};
try {
function a() {
/* 传入栈底方法 (c) 将不会触发 stack 属性的附加操作. */
Error.captureStackTrace(info, c);
return (0.5).toFixed(-1);
}
function b() {
a();
}
!function c() {
b();
}();
} catch (e) {
/* stack 信息未被附加. */
console.log(info.stack); // undefined
console.log(&quot;stack&quot; in info); // false
}
</code></pre>
<p>如果传入一个栈帧中不存在的函数, 则 <code>info.stack</code> 将返回 <code>&quot;&quot;</code> (空字符串):</p>
<pre><code class="lang-js">let info = {};
try {
function irrelevant() {
// Empty body.
}
function a() {
/* 传入一个与所有栈帧无关的函数, 将导致 stack 属性值变为空字符串. */
Error.captureStackTrace(info, irrelevant);
return (0.5).toFixed(-1);
}
function b() {
a();
}
!function c() {
b();
}();
} catch (e) {
console.log(info.stack); // &quot;&quot;
}
</code></pre>
</div>
</div>
</div>
<script src="assets/sh_javascript.js"></script>
<script src="assets/sh_java.js"></script>
<script src="assets/sh_main.js"></script>
<script src="plugins/docsify-copy-code@2.js"></script>
<script src="plugins/zoom-image.js"></script>
<script>
highlight(void 0, void 0, 'pre');
highlight(void 0, void 0, 'tt');
</script>
<!-- __TRACKING__ -->
</body>
</html>