ホームページ ウェブフロントエンド jsチュートリアル JavaScript エラー処理とスタック トレースの簡単な分析

JavaScript エラー処理とスタック トレースの簡単な分析

Nov 17, 2017 pm 01:27 PM
javascript js 追跡

コードの蓄積の過程で、エラー処理やスタック トレースの詳細が無視されることがありますが、これらの詳細に注意すると、テストやエラー処理に関連するライブラリを作成するのに非常に役立ちます。優れた処理を提供します。このアイデアにより、スタックの処理方法が大幅に改善されます。ユーザーのアサーションが失敗した場合、より迅速な情報が提供されます (ユーザーが見つけやすくするため)。同時に、Errors オブジェクトとその関連プロパティをより深く理解すると、

Errors.

( 関数の呼び出しスタックはどのように機能するか

) エラーについて話す前に、まず関数の呼び出しスタックの原理を理解してください。

関数が呼び出されると、関数はスタックの先頭にプッシュされ、関数が完了するとスタックの先頭から削除されます。

スタックの は、LIFO (後入れ先出し) として知られる後入れ先出しです。

例:

function c() {
    console.log('c');
}
function b() {
    console.log('b');
    c();
}
function a() {
    console.log('a');
    b();
}
a();
ログイン後にコピー


In 上記の例では、関数 a が実行されると、それが先頭に追加されます。次に、関数 a 内で関数 b が呼び出されるとき、関数 b はスタックの先頭にプッシュされます。関数 c が

にあるとき、関数 b の内部部分も呼び出されます。スタックの最上位。

関数 c が実行されているとき、スタックには a、b、c が (この順序で) 含まれます。

関数 c の実行が終了すると、スタックの最上位から削除され、その後コントロールが削除されます。関数呼び出しのフローは関数 b に戻り、関数 b の実行が終了すると、関数 b もスタックの先頭から削除され、最後に関数呼び出し

の制御フローが関数 b に戻ります。 、関数 a も実行後にスタックの先頭から削除されます

デモでスタックの動作をよりよく示すために、console.trace() を使用して現在のスタック データをコンソールに出力できます。同時に、出力スタック データを上から下の順序で読み取る必要があります

function c() {
    console.log('c');
    console.trace();
}
function b() {
    console.log('b');
    c();
}
function a() {
    console.log('a');
    b();
}
a();
ログイン後にコピー

ノードの REPL モードで上記のコードを実行すると、次の出力が得られます:

Trace
    at c (repl:3:9)
    at b (repl:3:1)
    at a (repl:3:1)
    at repl:1:1 // <-- For now feel free to ignore anything below this point, these are Node&#39;s internals
    at realRunInThisContextScript (vm.js:22:35)
    at sigintHandlersWrap (vm.js:98:12)
    at ContextifyScript.Script.runInThisContext (vm.js:24:12)
    at REPLServer.defaultEval (repl.js:313:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
ログイン後にコピー

関数 c からの呼び出し 出力するとき、スタックには関数 a、b、c が含まれています。

関数 c が完了した後、現在のスタック データを関数 b で出力すると、関数 c がスタックの先頭から削除されていることがわかります。 . この時点では、スタックには関数 a と関数 b のみが含まれています。

function c() {
    console.log(&#39;c&#39;);
}
function b() {
    console.log(&#39;b&#39;);
    c();
    console.trace();
}
function a() {
    console.log(&#39;a&#39;);
    b();
}
ログイン後にコピー

ご覧のとおり、関数 c が完了した後、スタックの先頭から削除されています。プログラムの実行中にエラーが発生すると、通常、Error オブジェクトがスローされます。Error オブジェクトは、ユーザー定義のエラー オブジェクト継承のプロトタイプとして使用できます。 Error.prototype オブジェクトには、次のプロパティが含まれます。

constructor – コンストラクター。インスタンスを指します

message – エラー メッセージ

name – エラーの名前 (タイプ)

上記は Error.prototype の標準プロパティです。さらに、さまざまな実行環境にはそれぞれ固有のプロパティがあります。 Node、Firefox、Chrome、Edge、IE 10 以降、Opera および Safari 6 以降

このような環境では、Error オブジェクトにはエラーのスタック トレースが含まれる stack 属性があり、エラー インスタンスのスタック トレースにはすべてが含まれます。コンストラクターの後のスタック構造

特定のプロパティについては、MDN のこの記事を参照してください。

エラーをスローするには、 throw キーワードを使用する必要があります。スローされたエラーをキャッチするには、try...catch を使用して、エラーを実行する可能性のあるコードを含める必要があります。Catch のパラメーターは、実行されたエラー インスタンスです。

Java と同様に、JavaScript では、後で、finally キーワードを使用することもできます。 try/catch. エラーを処理した後、finally ステートメント ブロックでクリーンアップ作業を行うことができます。

上記の構文では、catch ブロックを続けなくても try ブロックを使用できますが、その後にはfinally が続く必要があります。これは、3 つの異なる try ステートメント形式があることを意味します:

try...catch

try.. .finally

try...catch...finally


Try ステートメントを Try ステートメントに埋め込むこともできます:

Trace
    at b (repl:4:9)
    at a (repl:3:1)
    at repl:1:1  // <-- For now feel free to ignore anything below this point, these are Node&#39;s internals
    at realRunInThisContextScript (vm.js:22:35)
    at sigintHandlersWrap (vm.js:98:12)
    at ContextifyScript.Script.runInThisContext (vm.js:24:12)
    at REPLServer.defaultEval (repl.js:313:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.onLine (repl.js:513:10)
ログイン後にコピー

try ステートメントを catch またはfinallyに埋め込むこともできます:

try {
    try {
        throw new Error(&#39;Nested error.&#39;); // The error thrown here will be caught by its own `catch` clause
    } catch (nestedErr) {
        console.log(&#39;Nested catch&#39;); // This runs
    }
} catch (err) {
    console.log(&#39;This will not run.&#39;);
}
ログイン後にコピー

エラーがスローされたときに、Error オブジェクトの代わりに単純な値をスローするだけで済みます。これは見た目はクールで許可されていますが、特に他の人のコードを扱う必要がある一部のライブラリやフレームワーク開発者にとっては、参照する標準がないため、何が期待できるかを知る方法がなく、推奨されるアプローチではありません。ユーザーが Error オブジェクトをスローすることを信頼することはできません。ユーザーは単に文字列または数値をスローする可能性があるためです。これは、スタック情報やその他のメタ情報を扱うことが難しいことも意味します。例:

try {
    console.log(&#39;The try block is running...&#39;);
} finally {
    try {
        throw new Error(&#39;Error inside finally.&#39;);
    } catch (err) {
        console.log(&#39;Caught an error inside the finally block.&#39;);
    }
}
ログイン後にコピー

ユーザーが関数 runWithoutThrowing に渡したパラメーターがエラー オブジェクトをスローした場合、上記のコードは通常どおりエラーをキャッチできます。その後、文字列をスローすると、いくつかの問題が発生します。

function runWithoutThrowing(func) {
    try {
        func();
    } catch (e) {
        console.log(&#39;There was an error, but I will not throw it.&#39;);
        console.log(&#39;The error\&#39;s message was: &#39; + e.message)
    }
}
function funcThatThrowsString() {
    throw &#39;I am a String.&#39;;
}
runWithoutThrowing(funcThatThrowsString);
ログイン後にコピー

现在第二个 console.log 会输出undefined. 这看起来不是很重要, 但如果你需要确保 Error 对象有一个特定的属性或者用另一种方式来处理 Error 对象的特定属性(例如 Chai的throws断言的做法), 你就得做大量的工作来确保程序的正确运行.同时, 如果抛出的不是 Error 对象, 也就获取不到 stack 属性.

Errors 也可以被作为其它对象, 你也不必抛出它们, 这也是为什么大多数回调函数把 Errors 作为第一个参数的原因. 例如:

const fs = require(&#39;fs&#39;);
fs.readdir(&#39;/example/i-do-not-exist&#39;, function callback(err, dirs) {
    if (err instanceof Error) {
        // `readdir` will throw an error because that directory does not exist
        // We will now be able to use the error object passed by it in our callback function
        console.log(&#39;Error Message: &#39; + err.message);
        console.log(&#39;See? We can use Errors without using try statements.&#39;);
    } else {
        console.log(dirs);
    }
});
ログイン後にコピー

最后, Error 对象也可以用于 rejected promise, 这使得很容易处理 rejected promise:

new Promise(function(resolve, reject) {
    reject(new Error(&#39;The promise was rejected.&#39;));
}).then(function() {
    console.log(&#39;I am an error.&#39;);
}).catch(function(err) {
    if (err instanceof Error) {
        console.log(&#39;The promise was rejected with an error.&#39;);
        console.log(&#39;Error Message: &#39; + err.message);
    }
});
ログイン後にコピー

处理堆栈

这一节是针对支持 Error.captureStackTrace的运行环境, 例如Nodejs.

Error.captureStackTrace 的第一个参数是 object, 第二个可选参数是一个 function.Error.captureStackTrace 会捕获堆栈信息, 并在第一个参数中创建

stack 属性来存储捕获到的堆栈信息. 如果提供了第二个参数, 该函数将作为堆栈调用的终点. 因此, 捕获到的堆栈信息将只显示该函数调用之前的信息.

用下面的两个demo来解释一下. 第一个, 仅将捕获到的堆栈信息存于一个普通的对象之中:

const myObj = {};
function c() {
}
function b() {
    // Here we will store the current stack trace into myObj
    Error.captureStackTrace(myObj);
    c();
}
function a() {
    b();
}
// First we will call these functions
a();
// Now let&#39;s see what is the stack trace stored into myObj.stack
console.log(myObj.stack);
// This will print the following stack to the console:
//    at b (repl:3:7) <-- Since it was called inside B, the B call is the last entry in the stack
//    at a (repl:2:1)
//    at repl:1:1 <-- Node internals below this line
//    at realRunInThisContextScript (vm.js:22:35)
//    at sigintHandlersWrap (vm.js:98:12)
//    at ContextifyScript.Script.runInThisContext (vm.js:24:12)
//    at REPLServer.defaultEval (repl.js:313:29)
//    at bound (domain.js:280:14)
//    at REPLServer.runBound [as eval] (domain.js:293:12)
//    at REPLServer.onLine (repl.js:513:10)
ログイン後にコピー

从上面的示例可以看出, 首先调用函数 a(被压入堆栈), 然后在 a 里面调用函数 b(被压入堆栈且在a之上), 然后在 b 中捕获到当前的堆栈信息, 并将其存储到 myObj 中. 所以, 在控制台输出的堆栈信息中仅包含了 a和 b 的调用信息.

现在, 我们给 Error.captureStackTrace 传递一个函数作为第二个参数, 看下输出信息:

const myObj = {};
function d() {
    // Here we will store the current stack trace into myObj
    // This time we will hide all the frames after `b` and `b` itself
    Error.captureStackTrace(myObj, b);
}
function c() {
    d();
}
function b() {
    c();
}
function a() {
    b();
}
// First we will call these functions
a();
// Now let&#39;s see what is the stack trace stored into myObj.stack
console.log(myObj.stack);
 
// This will print the following stack to the console:
//    at a (repl:2:1) <-- As you can see here we only get frames before `b` was called
//    at repl:1:1 <-- Node internals below this line
//    at realRunInThisContextScript (vm.js:22:35)
//    at sigintHandlersWrap (vm.js:98:12)
//    at ContextifyScript.Script.runInThisContext (vm.js:24:12)
//    at REPLServer.defaultEval (repl.js:313:29)
//    at bound (domain.js:280:14)
//    at REPLServer.runBound [as eval] (domain.js:293:12)
//    at REPLServer.onLine (repl.js:513:10)
//    at emitOne (events.js:101:20)
ログイン後にコピー


当将函数 b 作为第二个参数传给 Error.captureStackTraceFunction 时, 输出的堆栈就只包含了函数 b 调用之前的信息(尽管 Error.captureStackTraceFunction 是在函数 d 中调用的), 这也就是为什么只在控制台输出了 a. 这样处理方式的好处就是用来隐藏一些与用户无关的内部实现细节.

感谢大家阅读本篇文章,之后也会给大家带来关于JS,关于前端的一些小技巧,希望大家共同探讨,一起进步。


相关推荐:

JavaScript和ECMAScript 之间的区别

JavaScript刷新页面location.reload()的用法

JavaScript中正则表达式的含义与使用

以上がJavaScript エラー処理とスタック トレースの簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

推奨: 優れた JS オープンソースの顔検出および認識プロジェクト 推奨: 優れた JS オープンソースの顔検出および認識プロジェクト Apr 03, 2024 am 11:55 AM

顔の検出および認識テクノロジーは、すでに比較的成熟しており、広く使用されているテクノロジーです。現在、最も広く使用されているインターネット アプリケーション言語は JS ですが、Web フロントエンドでの顔検出と認識の実装には、バックエンドの顔認識と比較して利点と欠点があります。利点としては、ネットワーク インタラクションの削減とリアルタイム認識により、ユーザーの待ち時間が大幅に短縮され、ユーザー エクスペリエンスが向上することが挙げられます。欠点としては、モデル サイズによって制限されるため、精度も制限されることが挙げられます。 js を使用して Web 上に顔検出を実装するにはどうすればよいですか? Web 上で顔認識を実装するには、JavaScript、HTML、CSS、WebRTC など、関連するプログラミング言語とテクノロジに精通している必要があります。同時に、関連するコンピューター ビジョンと人工知能テクノロジーを習得する必要もあります。 Web 側の設計により、次の点に注意してください。

株価分析に必須のツール: PHP と JS を使用してローソク足チャートを描画する手順を学びます 株価分析に必須のツール: PHP と JS を使用してローソク足チャートを描画する手順を学びます Dec 17, 2023 pm 06:55 PM

株式分析に必須のツール: PHP および JS でローソク足チャートを描画する手順を学びます。特定のコード例が必要です。インターネットとテクノロジーの急速な発展に伴い、株式取引は多くの投資家にとって重要な方法の 1 つになりました。株価分析は投資家の意思決定の重要な部分であり、ローソク足チャートはテクニカル分析で広く使用されています。 PHP と JS を使用してローソク足チャートを描画する方法を学ぶと、投資家がより適切な意思決定を行うのに役立つ、より直感的な情報が得られます。ローソク足チャートとは、株価をローソク足の形で表示するテクニカルチャートです。株価を示しています

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

Apple 携帯電話を紛失して電源が切れた場合、その正確な位置を追跡するにはどうすればよいですか? Apple 携帯電話を紛失して電源が切れた場合、その正確な位置を追跡するにはどうすればよいですか? Mar 08, 2024 pm 02:30 PM

Apple の携帯電話を紛失して電源が切れた場合でも、復元することができます。方法も非常に簡単です。ユーザーは iCloud の公式 Web サイトにログインして検索することもできますし、同じく Apple の携帯電話を使用している友人が自分の携帯電話を使用することもできます。 iPhoneを検索します。 Apple 携帯電話を紛失して電源が切れた場合、その正確な位置を追跡するにはどうすればよいですか? 回答: iCloud の公式 Web サイトで検索するか、他の人の iPhone デバイスを借りて見つけてください。電源を切っていても見つかります。 2. ユーザーは iCloud 公式 Web サイトに直接ログインし、「iPhone を探す」をクリックして、正しいアカウント番号を必ず入力してください。 3. 電話機を回復できるように、自分のアカウントが紛失した電話機のアカウントと一致していることを確認してください。 4. 電話機の電源が入っていて接続されている場合

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

PHP および JS 開発のヒント: 株価ローソク足チャートの描画方法をマスターする PHP および JS 開発のヒント: 株価ローソク足チャートの描画方法をマスターする Dec 18, 2023 pm 03:39 PM

インターネット金融の急速な発展に伴い、株式投資を選択する人がますます増えています。株式取引では、ローソク足チャートは一般的に使用されるテクニカル分析手法であり、株価の変化傾向を示し、投資家がより正確な意思決定を行うのに役立ちます。この記事では、PHP と JS の開発スキルを紹介し、株価ローソク足チャートの描画方法を読者に理解してもらい、具体的なコード例を示します。 1. 株のローソク足チャートを理解する 株のローソク足チャートの描き方を紹介する前に、まずローソク足チャートとは何かを理解する必要があります。ローソク足チャートは日本人が開発した

See all articles