1124 lines
52 KiB
HTML
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 & 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 (异常) 对象, 但章节标题依然采用 "异常" (而非 "错误").</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 < MIN || num > MAX) {
|
|
throw new RangeError(`Number ${num} must be between ${MIN} and ${MAX}.`);
|
|
}
|
|
};
|
|
|
|
try {
|
|
check(523);
|
|
} catch (e) {
|
|
if (e instanceof RangeError) {
|
|
console.error("发生越界错误.");
|
|
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 === 'undefined') {
|
|
throw new ReferenceError("Invalid options.");
|
|
}
|
|
/* 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("...");
|
|
} catch (e) {
|
|
if (e instanceof SyntaxError) {
|
|
console.error("发生语法错误, 位于 eval.");
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
/* 复现. */
|
|
|
|
// Firefox 103.0 - SyntaxError: expected expression, got '??'.
|
|
// Node.js 17.3.0 - SyntaxError: Unexpected token '??'.
|
|
// 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('Hello', "someFile.js", 10);
|
|
} catch (e) {
|
|
console.log(e instanceof TypeError); // true
|
|
console.log(e.message); // "Hello"
|
|
console.log(e.name); // "TypeError"
|
|
console.log(e.fileName); // "someFile.js"
|
|
console.log(e.lineNumber); // 10
|
|
}
|
|
|
|
/* 复现. */
|
|
|
|
// TypeError: Cannot call method "f" of null.
|
|
null.f();
|
|
|
|
// TypeError: java is not a function, it is object.
|
|
java();
|
|
|
|
// TypeError: day is not a function, it is string.
|
|
[].every("day");
|
|
</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('Hello', 'someFile.js', 10);
|
|
} catch (e) {
|
|
console.log(e instanceof URIError); // true
|
|
console.log(e.message); // "Hello"
|
|
console.log(e.name); // "URIError"
|
|
console.log(e.fileName); // "someFile.js"
|
|
console.log(e.lineNumber); // 10
|
|
}
|
|
|
|
/* 复现. */
|
|
|
|
// URIError: Malformed URI sequence.
|
|
decodeURIComponent('%');
|
|
</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("发生内部错误: 未知的预置 App.");
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
/* 复现. */
|
|
|
|
// InternalError: Java method "vibrate" 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('Hello', 'someFile.js', 10);
|
|
} catch (e) {
|
|
console.log(e instanceof EvalError); // true
|
|
console.log(e.message); // "Hello"
|
|
console.log(e.name); // "EvalError"
|
|
console.log(e.fileName); // "someFile.js"
|
|
console.log(e.lineNumber); // 10
|
|
}
|
|
|
|
/* 复现. */
|
|
|
|
/* eval 抛出具体类型的错误, 而非 EvalError, 因此基本无法复现. */
|
|
|
|
// ReferenceError: "hello" is not defined.
|
|
eval("hello()");
|
|
|
|
/* 除非像上述 "创建 EvalError" 示例一样抛出错误, */
|
|
/* 或在 eval 中显式抛出 EvalError, */
|
|
/* 但这样做通常没有意义. */
|
|
|
|
// EvalError: test
|
|
eval("throw EvalError('test')");
|
|
</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('h1').item(0);
|
|
let refnode = node.nextSibling;
|
|
let newnode = document.createTextNode('test');
|
|
node.insertBefore(newnode, refnode); /* 抛出 DOMException 异常. */
|
|
</code></pre>
|
|
<p>DOMException 包含详细的名称分类, 如 [ "NotFoundError" / "InvalidStateError" / "NoModificationAllowedError" ] 等, 详情参阅 <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 "${msg}" must end with "Fruit"`;
|
|
this.name = this.constructor.name;
|
|
}
|
|
|
|
InvalidFruitError.prototype = Object.create(Error.prototype, {
|
|
constructor: { value: InvalidFruitError },
|
|
});
|
|
|
|
function ensureFruitName(name) {
|
|
if (!name.endsWith("Fruit")) {
|
|
throw new InvalidFruitError(name);
|
|
}
|
|
}
|
|
|
|
// InvalidFruitError: Name of "coconut" must end with "Fruit"...
|
|
[ "appleFruit", "bananaFruit", "coconut" ].forEach(ensureFruitName);
|
|
</code></pre>
|
|
<ul>
|
|
<li>模拟标准内置对象 Error 的行为:</li>
|
|
</ul>
|
|
<pre><code class="lang-js">function InvalidFruitError(msg) {
|
|
this.message = `Name of "${msg}" must end with "Fruit"`;
|
|
this.name = this.constructor.name;
|
|
this.toString = () => `${this.name}: ${this.message}`;
|
|
}
|
|
|
|
function ensureFruitName(name) {
|
|
if (!name.endsWith("Fruit")) {
|
|
throw new InvalidFruitError(name);
|
|
}
|
|
}
|
|
|
|
// InvalidFruitError: Name of "coconut" must end with "Fruit"...
|
|
[ "appleFruit", "bananaFruit", "coconut" ].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 = 'CustomError';
|
|
|
|
try {
|
|
throw new CustomError('baz', 'bazMessage');
|
|
} 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("foo");
|
|
</code></pre>
|
|
<pre><code class="lang-kotlin">/* Kotlin. */
|
|
|
|
/* Kotlin 语言无 new 关键字. */
|
|
throw Exception("foo");
|
|
</code></pre>
|
|
<pre><code class="lang-js">/* JavaScript. */
|
|
|
|
/* Error 实例. */
|
|
throw new Error("foo");
|
|
|
|
/* Error 实例 (new 关键字省略). */
|
|
throw Error("foo");
|
|
|
|
/* 数字或字符串等表达式. */
|
|
throw "foo"; /* 合法. */
|
|
throw 23; /* 合法. */
|
|
throw true; /* 合法. */
|
|
|
|
/* 对象. */
|
|
throw {
|
|
name: "CustomError",
|
|
message: "test",
|
|
__proto__: Error.prototype,
|
|
};
|
|
|
|
/* 自定义 "类" 的实例. */
|
|
function TestError(msg) {
|
|
this.message = msg;
|
|
this.name = this.constructor.name;
|
|
this.toString = () => `${this.name}: ${this.message}`;
|
|
}
|
|
|
|
throw new TestError("foo"); /* 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("hello");
|
|
} catch (e) {
|
|
console.log(e.message); // "hello"
|
|
}
|
|
</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>又名 "捕捉块".</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("Class name is null");
|
|
}
|
|
}
|
|
|
|
classForName("NonExistingClass"); // 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("Class name is null");
|
|
}
|
|
}
|
|
</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 "error";
|
|
} 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("test");
|
|
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 类型的名称, 初始值为 "Error".</p>
|
|
<pre><code class="lang-js">console.log(new SyntaxError('hello').name); // "SyntaxError"
|
|
|
|
try {
|
|
throw TypeError('world');
|
|
} catch (e) {
|
|
console.log(e.name); // "TypeError"
|
|
}
|
|
</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('hello').name); // "hello"
|
|
|
|
try {
|
|
Math.random().toFixed(-1);
|
|
} catch (e) {
|
|
console.log(e.message); // "精度 -1 超出范围."
|
|
}
|
|
</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('hello');
|
|
}();
|
|
} 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) => a.concat([ b.getFunctionName() ]), []);
|
|
};
|
|
try {
|
|
!function test() {
|
|
throw Error('hello');
|
|
}();
|
|
} 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("hello");
|
|
} 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("hello");
|
|
} catch (e) {
|
|
console.log(e.fileName); /* e.g. "/storage/emulated/0/Scripts/test.js" */
|
|
}
|
|
</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) {
|
|
// '[JavaException: android.content.ActivityNotFoundException: No Activity found to handle Intent { flg=0x10000000 }]'
|
|
console.log(e);
|
|
|
|
console.log(e.javaException !== undefined); // true
|
|
|
|
/* 借助 e.javaException 类型处理不同的异常. */
|
|
if (e.javaException instanceof org.json.JSONException) {
|
|
console.error('JSON 解析错误');
|
|
throw (e);
|
|
}
|
|
if (e.javaException instanceof android.content.ActivityNotFoundException) {
|
|
console.error('指定的 Activity 不存在');
|
|
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) {
|
|
// '[ReferenceError: "f" is not defined.]'
|
|
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('hello');
|
|
console.log(errA.toString()); // "Error: hello"
|
|
|
|
let errB = new TypeError('world');
|
|
console.log(errB.toString()); // "TypeError: world"
|
|
|
|
errB.name = 'Banana';
|
|
console.log(errB.toString()); // "Banana: world"
|
|
|
|
errB.message = "yellow";
|
|
console.log(errB.toString()); // "Banana: yellow"
|
|
</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('hello');
|
|
console.log(err.toSource()); // (new Error("hello", ""))
|
|
|
|
try {
|
|
Math.random().toFixed(-1);
|
|
} catch (e) {
|
|
console.log(e.toSource()); // (new RangeError("\u7cbe\u5ea6 -1 \u8d85\u51fa\u8303\u56f4.", "\u8fdc\u7a0b$Untitled-52js", 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 = "hello";
|
|
</code></pre>
|
|
<p>注意与 0 的区分, 将数量限制设置为 0 表示不显示栈追踪信息, 即禁用栈追踪收集.</p>
|
|
<pre><code class="lang-js">let infoA = {};
|
|
let infoB = {};
|
|
|
|
try {
|
|
throw Error("hello");
|
|
} 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>用于自定义栈追踪信息格式, 该属性以函数形式发挥作用, 因此文档称之为 "格式函数".</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 = "hello"; /* 无任何效果. */
|
|
</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 => `${f.getFunctionName()}: ${f.getLineNumber()}`).join('\n');
|
|
};
|
|
try {
|
|
!function test() {
|
|
throw Error('hello');
|
|
}();
|
|
} 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 (栈顶) -> b -> 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("stack" in info); // false
|
|
}
|
|
</code></pre>
|
|
<p>如果传入一个栈帧中不存在的函数, 则 <code>info.stack</code> 将返回 <code>""</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); // ""
|
|
}
|
|
</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> |