前の言葉
ウェブアプリケーション開発にはエラー処理が重要です。事前に可能なエラーを予測することはできず、回復戦略を事前に採用することはできません。これにより、ユーザーエクスペリエンスが低下する可能性があります。 JavaScriptエラーは、開発者としてWebページを使用できなくなる可能性があるため、いつ、なぜ、何が起こるかを知る必要があります。この記事では、JavaScriptのエラー処理メカニズムを詳細に紹介します
エラーオブジェクト
エラーオブジェクトは、エラー情報を含むオブジェクトであり、JavaScriptのネイティブオブジェクトです。コードの解析または実行中にエラーが発生すると、JavaScriptエンジンは自動的にエラーオブジェクトのインスタンスを生成してスローし、エラーが発生するとプログラム全体が中断されます。
console.log(t); // conted referenceerror:tは定義されていません
ECMA-262エラーオブジェクトには、メッセージと名前の2つのプロパティが含まれることを指定します。メッセージ属性はエラーメッセージを保存し、名前属性はエラータイプを保存します
コードコピーは次のとおりです。
//一般的に、トライキャッチステートメントを使用してエラーをキャッチします
試す{
t;
} catch(ex){
console.log(ex.message); // tは定義されていません
console.log(ex.name); // referenceError
}
また、ブラウザはエラーオブジェクトのプロパティを拡張し、他の関連情報を追加しました。その中で、ブラウザメーカーが最も実装しているのはスタック属性です。これは、スタックトレース情報を示しています(Safariはサポートしていません)
コードコピーは次のとおりです。
試す{
t;
} catch(ex){
console.log(ex.stack); //@file:/// d:/wamp/www/form.html:12:2
}
もちろん、エラー()コンストラクターを使用してエラーオブジェクトを作成できます。メッセージパラメーターが指定されている場合、エラーオブジェクトはメッセージプロパティとして使用します。指定されていない場合、プロパティの値として事前定義されたデフォルト文字列を使用します
コードコピーは次のとおりです。
新しいエラー();
新しいエラー(メッセージ);
//一般的に、スローステートメントを使用してエラーをスローします
新しいエラー( 'test'); // cont cast error:テスト
新しいエラー(); // cont cast Errorをスローします
コードコピーは次のとおりです。
function userError(メッセージ){
this.message = message;
this.name = "userError";
}
userError.prototype = new Error();
userError.prototype.constructor = userError;
新しいuserError( "errormessage"); // cound uncaught userError:errormessage
エラー()コンストラクターが新しい演算子を使用せずに関数のように直接呼ばれる場合、その動作は新しい演算子が呼び出されたときと同じです
コードコピーは次のとおりです。
エラー();
エラー(メッセージ);
スローエラー( 'test'); // cont caughtエラー:テスト
スローエラー();
エラーオブジェクトには、エラーオブジェクトのメッセージ属性を返すtoString()メソッドがあります。
コードコピーは次のとおりです。
var test = new Error( 'testerror');
console.log(test.tostring()); // 'エラー:testerror'
エラータイプ
コード実行中に発生する可能性のあるエラーには多くの種類があります。各エラーには対応するエラータイプがあり、エラーが発生すると、対応するタイプのエラーオブジェクトがスローされます。 ECMA-262は、次の7つのエラータイプを定義します。
コードコピーは次のとおりです。
エラー
evalError(評価エラー)
remasherror(rasinererror)
参照エラー(参照エラー)
構文(構文エラー)
TypeRROR(タイプエラー)
urierror(uriエラー)
ここで、エラーはベースタイプであり、他のエラータイプがこのタイプから継承されます。したがって、すべてのエラータイプは、同じプロパティのセットを共有します。エラータイプエラーはまれであり、ある場合、ブラウザによってもスローされます。このベースタイプの主な目的は、開発者がカスタムエラーをスローすることです
【evalError(評価エラー)】
評価関数が正しく実行されない場合、評価エラーがスローされます。このエラータイプはES5に表示されなくなりましたが、以前のコードとの互換性を確保するために引き続き保存されます。
【レンジャー(rasinError)】
値が対応する範囲を超えている場合、主にアレイの長さ範囲を超えて数値範囲を超える場合、radeErrorタイプの誤差がトリガーされます。
コードコピーは次のとおりです。
new Array(-1); // Uncaught raseerror:無効な配列長
new Array(number.max_value); // Uncaught raseerror:無効な配列長
(1234).toexponential(21); // uncaught raseerror:toexponential()引数は0〜20でなければなりません
(1234).toexponential(-1); //// Uncaught raseerror:toexponential()引数は0〜20でなければなりません
【REFERENTERROR(参照エラー)】
ReferenceErrorは、不可能な変数またはLValueタイプのエラーを参照するときにトリガーされます。
a; // conged referenceError:aは定義されていません
1 ++; // conged referenceError:ポストフィックス操作における無効な左側の式
【syntaxerror(syntaxerror)】
構文ルールが満たされていない場合、SyntaxErrorがスローされます(構文エラー)
コードコピーは次のとおりです。
//変数名が間違っています
var 1a; // excaught syntaxerror:予期しない数
//括弧がありません
console.log 'hello'); // contabed syntaxerror:予期しない文字列
【タイプエラー(タイプエラー)】
TypeErrorタイプのエラーは、予期しないタイプが変数に保存されている場合、または存在しない方法にアクセスするときに発生します。エラーの原因は多様ですが、最終的には、特定のタイプの操作を実行するときに変数のタイプが要件を満たしていないためです。
コードコピーは次のとおりです。
var o = new 10; // Uncaught TypeRror:10はコンストラクターではありません
alert(true in 'name in true); // contaught typeerror:「オペレーターで」を使用できないため、trueで「名前」を検索
function.prototype.tostring.call( 'name'); // uncaught typeerror:function.prototype.tostringは一般的ではありません
【ウリエラー(URIエラー)】
urierrorは、URI関連の関数のパラメーターが正しくない場合にスローされるエラーです。主に6つの関数が含まれます:encodeuri()、decodeuri()、encodeuricomponent()、decodeuricomponent()、estase()、およびunescape()。
decodeuri( '%2'); // urierror:uri malformed
エラーイベント
Try-Catchで処理されないエラーは、ウィンドウオブジェクトのエラーイベントをトリガーします
エラーイベントは、エラーメッセージ、エラーの配置場所のURL、および行番号の3つのパラメーターを受信できます。ほとんどの場合、URLはドキュメントの場所のみを提供するため、エラーメッセージのみが便利であり、行番号は埋め込まれたJavaScriptコードまたは外部ファイルからのコードの行を指します。
エラーイベントハンドラーを指定するには、DOM0レベルのテクノロジーを使用するか、DOM2レベルのイベントの標準形式を使用できます。
コードコピーは次のとおりです。
// dom0レベル
window.onerror = function(message、url、line){
アラート(メッセージ);
}
// dom2レベル
window.addeventlistener( "error"、function(message、url、line){
アラート(メッセージ);
});
ブラウザが標準のエラーメッセージを表示するかどうかは、Onerrorの返品値に依存します。戻り値がfalseの場合、エラーメッセージがコンソールに表示されます。返品値が真の場合、表示されません
コードコピーは次のとおりです。
//コンソールにエラーメッセージが表示されます
window.onerror = function(message、url、line){
アラート(メッセージ);
falseを返します。
}
A;
//コンソールはエラーメッセージを表示しません
window.onerror = function(message、url、line){
アラート(メッセージ);
trueを返します。
}
A;
このイベントハンドラーは、ブラウザのレポートエラーを回避するための最後の防衛線です。理想的には、可能な限り使用しないでください。 Try-Catchステートメントを適切に使用できる限り、ブラウザにエラーが渡されず、エラーイベントはトリガーされません。
画像はエラーイベントもサポートしています。画像のSRC特性のURLが認識された画像形式を返すことができない限り、エラーイベントがトリガーされます。この時点で、エラーイベントはDOM形式に従い、ターゲットとして画像をターゲットとするイベントオブジェクトを返します
画像がロードされると警告ボックスが表示されます。エラーイベントが発生すると、画像のダウンロードプロセスが終了しました。つまり、再度ダウンロードできません。
コードコピーは次のとおりです。
var image = new Image();
image.src = 'smilex.gif';
image.onerror = function(e){
console.log(e);
}
ステートメントを投げてエラーをスローします
スローステートメントは、エラーをスローするために使用されます。エラーがスローされたら、スローステートメントに値を指定する必要があります。この値はどのタイプですか?要件はありません。
[注]エラーをスローするプロセスがブロックされ、後続のコードは実行されません
コードコピーは次のとおりです。
12345を投げる;
「ハローワールド」を投げる;
真実を投げる;
Throw {name: 'JavaScript'};
スローステートメントを使用して、エラーオブジェクトを手動で投げることができます
コードコピーは次のとおりです。
新しいエラーをスローします(「何か悪いことが起こった」);
新しいsyntaxerror( 'I don/' t your syntax。 ')を投げます。
新しいTypeErrorを投げます( 'どのタイプの変数を連れて行ってくれますか?');
新しいrasinErrorを投げます( '申し訳ありません、あなたはただ範囲を持っていません。」);
新しいEvalError( 'that non/' t avalute。 ')を投げます。
新しいurierror( 'uri、それはあなたですか?')を投げます。
新しいReferenceErrorを投げます(「あなたはあなたの参照を適切に引用しなかった/」);
プロトタイプチェーンを使用すると、エラーを継承することによりカスタムエラータイプを作成することもできます(第6章でプロトタイプチェーンが導入されます)。この時点で、新しく作成されたエラータイプの名前とメッセージ属性を指定する必要があります
ブラウザは、他のエラータイプと同様にエラーから継承されたカスタムエラータイプを扱います。カスタムエラーを作成することは、エラーをキャッチしてブラウザエラーとは異なる方法で扱う場合に役立ちます。
コードコピーは次のとおりです。
function customerror(message){
this.name = 'CustomError';
this.message = message;
}
customerror.prototype = new Error();
新しいCustomError( 'my message')を投げます。
スローステートメントが発生した場合、コードはすぐに実行を停止します。コードは、Try-Catchステートメントがスローされた値をキャプチャした場合にのみ実行され続けます。
より詳細な説明は、例外がスローされると、JavaScriptインタープリターはすぐに現在実行中のロジックを停止し、近くの例外ハンドラーにジャンプします。例外ハンドラーは、Try-CatchステートメントのCatch句に記述されています。例外をスローするコードブロックに関連するCACT条項がない場合、インタープリターは高レベルのクローズドコードブロックをチェックして、関連する例外ハンドラーがあるかどうかを確認します。例外ハンドラーが見つかるまで。例外をスローする関数がTry-Catchステートメントを処理しない場合、例外は関数を呼び出すコードに上向きに伝播されます。このようにして、例外は、JavaScriptメソッドの語彙構造とコールスタックに沿って上方に伝播されます。例外ハンドラーが見つからない場合、JavaScriptは例外をプログラムエラーとして処理し、ユーザーに報告します
catchステートメントとキャッチエラーを試してください
ECMA-262エディション3は、エラーをキャッチして処理するために使用されるJavaScriptの例外を処理する標準的な方法として、トライキャッチステートメントを紹介します
その中で、Try句は、処理する必要がある例外が配置されているコードブロックを定義します。キャッチ句は、Try句に従います。 Tryブロックのどこかで例外が発生すると、キャッチ内のコードロジックが呼び出されます。 Catch句の後に、最終的なブロックが続き、クリーニングコードが配置されます。 Tryブロックで例外が発生するかどうかにかかわらず、最終的なブロック内のロジックは常に実行されます。 CATCHと最終的にオプションですが、Try句では、2つのうち少なくとも1つが完全なステートメントを形成する必要があります。
すべてのtry/catch/最後にステートメントブロックは、巻き毛のブレースで囲む必要があります。ここのブレースが必要です。条項に1つのステートメントしかない場合でも、カーリーブレースは省略できません。
試す{
//一般的に言えば、ここのコードは問題なく最初から最後まで開始されます
//しかし、スローステートメントによって直接スローされるか、メソッドを呼び出すことで間接的に例外がスローされることがあります
} catch(e){
// TRYステートメントブロックによって例外がスローされている場合にのみ、ここのコードが実行されます
//ここで、ローカル変数eによってスローされたエラーオブジェクトまたはその他の値への参照を取得できます
//ここのコードブロックは、何らかの理由でこの例外を処理したり、この例外を無視したり、スローステートメントを介して例外を再スローすることもできます
} ついに{
// Tryステートメントが例外をスローするかどうかに関係なく、最終的にロジックが常に実行されます。 Tryステートメントブロックを終了する方法は次のとおりです。
// 1。正常に終了するには、ステートメントブロックの最後のステートメントを実行します
// 2。休憩、継続、または復元されたステートメントを終了します
// 3。例外を投げると、例外はCATCH句によってキャッチされます
// 4。例外を投げる、例外が捕らえられず、上向きに伝播し続ける
}
通常、Tryステートメントブロックにエラーをスローする可能性のあるすべてのコードを配置し、Catch Blockでエラー処理に使用されるコードを配置します
TRYブロックエラーの任意のコードが発生した場合、コード実行プロセスがすぐに終了し、CATCHブロックが実行されます。この時点で、Catchブロックはエラーメッセージ付きのオブジェクトを受信します。このオブジェクトに含まれる実際の情報は、ブラウザからブラウザまでさまざまですが、一般的なのはエラーメッセージを保存するメッセージ属性があることです
[注]エラーオブジェクトに必ず名前を付けてください。それを空にすると、構文エラーが報告されます。
コードコピーは次のとおりです。
試す{
Q;
} catch(error){
アラート(error.message); // qは定義されていません
}
// Uncaught syntaxerror:予期しないトークン)
試す{
Q;
}キャッチ(){
アラート(error.message);
}
CACTは、TRYコードブロックによってスローされた値を示すパラメーターを受け入れます
コードコピーは次のとおりです。
function throwit(例外){
試す {
例外をスローします。
} catch(e){
console.log( 'catch:'+ e);
}
}
throwit(3); // catch:3
throwit( 'hello'); // catch:hello
throwit(newエラー( 'エラーが発生した')); // catch:エラー:エラーが発生しました
キャッチコードブロックがエラーをキャッチした後、プログラムは中断されず、通常のプロセスに従って実行され続けます。
コードコピーは次のとおりです。
試す{
「エラー」を投げる;
} catch(e){
console.log(111);
}
console.log(222);
// 111
// 222
さまざまな種類のエラーをキャッチするために、CATCHコードブロックに判断ステートメントを追加できます
コードコピーは次のとおりです。
試す {
foo.bar();
} catch(e){
if(e instanceof vertherror){
console.log(e.name + ":" + e.message);
} else if(e instanceof ravenserror){
console.log(e.name + ":" + e.message);
}
// ...
}
最終的な句はTry-Catchステートメントではオプションですが、最終的な句が使用されると、そのコードは何があっても実行されます。言い換えれば、TRYステートメントブロックのすべてのコードが正常に実行され、最終的に条項が実行されます。 ERRORのためにCatchステートメントブロックが実行された場合、最終句はまだ実行されます。コードに最終的な条項が含まれている限り、TryまたはCatchステートメントブロックにどのようなコードが含まれていても、戻りステートメントにさえ、最終句の実行は防止されません。
コードコピーは次のとおりです。
//キャッチステートメントブロックがないため、エラーはキャッチされません。最終的なコードブロックを実行した後、エラーがスローされるとプログラムが中断されます。
function cleansup(){
試す {
新しいエラーをスロー( 'エラー...');
console.log( 'この行は実行されません');
} ついに {
console.log( '完全なクリーニング作業');
}
}
cleansup();
//クリーニング作業を完了します
//エラー:何かがうまくいかなかった...
コードコピーは次のとおりです。
関数testfinnally(){
試す{
戻る2;
} catch(error){
返品1;
} ついに{
0を返します。
}
}
testfinnally(); // 0
[注]最終的なコードブロックが実行される前に、返信ステートメントのカウントの値が取得されます。
コードコピーは次のとおりです。
var count = 0;
function countup(){
試す {
返品数;
} ついに {
count ++;
}
}
countup(); // 0
console.log(count); // 1
コードコピーは次のとおりです。
関数f(){
試す {
console.log(0);
「バグ」を投げる;
} catch(e){
console.log(1);
trueを返します。 //この文は、実行前に最終的なコードブロックの終了まで遅延していたでしょう
console.log(2); //実行されません
} ついに {
console.log(3);
falseを返します。 //この文は、以前の返品をカバーします
console.log(4); //実行されません
}
console.log(5); //実行されません
}
var result = f();
// 0
// 1
// 3
console.log(result); // false
【ヒント】ブロックレベルの範囲
トライキャッチステートメントの一般的な使用は、宣言された変数がキャッチ内でのみ有効であるブロックレベルのスコープを作成することです
ES6は、LETキーワードを導入して、宣言する変数のブロックレベルスコープを作成します。ただし、ES3とES5の現在の状況では、同様の効果を達成するためにトライキャッチステートメントを使用することがよくあります
次のコードから、EはCatch句の中にのみ存在し、他の場所から参照しようとするとエラーがスローされます。
コードコピーは次のとおりです。
試す{
新しいエラー(); //エラーを上回る
} catch(e){
console.log(e); //エラー(…)
}
console.log(e); // conted referenceerror:eは定義されていません
一般的なエラー
エラー処理のコアは、最初にコードでどのエラーが発生するかを知ることです。 JavaScriptはゆるく型付けされており、関数のパラメーターを検証しないため、エラーはコード中にのみ発生します。一般的に言えば、3種類のエラーに注意する必要があります:タイプ変換エラー、データ型エラー、および通信エラー
【型変換エラー】
タイプ変換エラーは、オペレーターを使用する場合、または値を自動的に変換する可能性のあるデータ型の別の言語構造を使用するときに発生します。
フロー制御ステートメントは、変換エラーを入力する傾向があります。 IFのようなステートメントは、次の操作を決定する前に、任意の値をブール値に自動的に変換します。特に声明の場合、不適切に使用された場合、それらは間違いを犯す可能性が最も高くなります。
未使用の名前の変数は、未定義の値が自動的に割り当てられます。未定義の値は、ブール値のfalseに変換できるため、次の関数のIFステートメントは、実際には3番目のパラメーターが提供される場合にのみ適用されます。問題は、falseに変換されることも未定義であるだけでなく、trueに変換できる文字列値のみでもないことです。たとえば、3番目のパラメーターが値0の場合、IFステートメントのテストが故障し、対数値1のテストが渡されます。
コードコピーは次のとおりです。
関数concat(str1、str2、str3){
var result = str1 + str2;
if(str3){//絶対にこのようではありません
結果 += str3;
}
返品結果;
}
フロー制御ステートメントで非ブール値を使用することは、非常に一般的なエラーソースです。このようなエラーを回避するには、条件を比較したときにブール値を渡す必要があります。実際、何らかの形の比較を実行するとこれを達成できます
コードコピーは次のとおりです。
関数concat(str1、str2、str3){
var result = str1 + str2;
if(typeof str3 == 'string'){//より適切です
結果 += str3;
}
返品結果;
}
【データ型エラー】
JavaScriptはゆるく入力されており、変数と関数パラメーターが使用されるまでデータ型が正しいことを確認するために比較されません。データ型エラーが発生しないようにするために、適切なデータ型検出コードのみを記述できます。データ型エラーは、機能をプロットするために予期しない値を渡すときに発生する可能性が最も高くなります
コードコピーは次のとおりです。
//非安全な機能では、アレイ以外の値がエラーを引き起こします
関数Reversesort(values){
if(values){
values.sort();
values.Reverse();
}
}
別の一般的な間違いは、パラメーターをnull値と比較することです。 nullと比較すると、対応する値がnullで未定義ではないことが保証されます。渡された値が有効であることを確認するには、ヌル値のみを検出するだけでは不十分です
コードコピーは次のとおりです。
//非安全な機能では、アレイ以外の値がエラーを引き起こします
関数Reversesort(values){
if(values!= null){
values.sort();
values.Reverse();
}
}
sort()メソッドを含むオブジェクト(配列ではなく)が渡されると、検出が渡されますが、reverse()関数を呼び出すとエラーが発生する場合があります
コードコピーは次のとおりです。
//非安全な機能では、アレイ以外の値がエラーを引き起こします
関数Reversesort(values){
if(typeof values.sort == 'function'){
values.sort();
values.Reverse();
}
}
どのタイプを渡すべきかを正確に知っている場合は、InstanceOFを使用してデータ型を検出することをお勧めします
コードコピーは次のとおりです。
//安全に、非アレイ値は無視されます
関数Reversesort(values){
if(values instance of array){
values.sort();
values.Reverse();
}
}
【通信エラー】
AJAXプログラミングの台頭により、Webアプリケーションがライフサイクル中に情報または機能を動的にロードすることが一般的になりました。ただし、JavaScriptとサーバー間の通信がエラーを引き起こす可能性があります
最も一般的な問題は、サーバーに送信する前に、データがencodeuricomponent()を使用してエンコードされていないことです。
コードコピーは次のとおりです。
//間違い
http://www.yourdomain.com/?redir=http://www.sometherdomain.com?a = b&c=d
// 'redir ='後のすべての文字列のecodeuricomponent()を呼び出すことができますこの問題は解決できます
http://www.yourdomain.com/?redir=http:%3a%2f%2fww.sometherdomain.com%3fa%3db%26c%3dd