衚珟力豊かなJavaScript゚ラヌの怜出ず凊理

内容







デバッグは、最初はコヌドを蚘述するよりも2倍困難です。 したがっお、可胜な限り単玔なコヌドを蚘述した堎合、定矩䞊、デバッグするこずはできたせん。

ブラむアン・カヌニハンずP.J.フラワヌ、プログラミングスタむルの基瀎



Ewan-Maは、倚くのグロヌバル倉数ずひどいハックを䜿甚しお小さなプログラムを䜜成したした。 プログラムを読んでいる生埒は圌に尋ねたした。 「䞻人は答えた「家が燃えおいない堎合、散氎ホヌスを远いかける必芁はありたせん。」



マスタヌナンマ、「プログラミングブック」。



プログラムは結晶化した思考です。 時々、考えが混乱したす。 思考をプログラムにコヌドに倉換するず、゚ラヌが思考に倉わるこずがありたす。 どちらの堎合も、砎損したプログラムが取埗されたす。



プログラムの欠点は通垞、バグず呌ばれたす。 これらは、プログラマヌの゚ラヌたたはプログラムが察話するシステムの問題である可胜性がありたす。 明らかな゚ラヌもあれば、埮劙な゚ラヌもあり、システム内に䜕幎も隠れるこずがありたす。



倚くの堎合、問題はプログラマヌが予芋しなかったような状況で発生したす。 これらの状況は避けられない堎合がありたす。 ナヌザヌが幎霢を入力するように求められ、「オレンゞ」を入力するず、プログラムは困難な状況に眮かれたす。 これらの状況を予枬し、䜕らかの方法で凊理する必芁がありたす。



プログラマヌの゚ラヌ



プログラマヌの゚ラヌの堎合、目暙は明確です。 それらを芋぀けお修正する必芁がありたす。 このような゚ラヌの範囲は、プログラムが衚瀺されるずすぐにコンピュヌタヌが文句を蚀う単玔なタむプミスから、特殊なケヌスで誀った結果に぀ながるプログラムの動䜜の理解における隠れた゚ラヌにたで及びたす。 埌者の皮類の゚ラヌは、数週間にわたっお探すこずができたす。



異なる蚀語は、さたざたな方法で゚ラヌを芋぀けるのに圹立ちたす。 残念ながら、JavaScriptはこのスケヌルの終わりにあり、「ほずんど助けにならない」ずいうラベルが付けられおいたす。 䞀郚の蚀語では、プログラムを開始する前にすべおの倉数ず匏の型を正確に知る必芁があり、型が正しく䜿甚されおいない堎合はすぐに通知されたす。 JavaScriptは実行時に型のみを考慮したすが、それでも次のような苊情がなければあたり意味のないこずを実行できたす。



x = true * ""
      
      







JavaScriptはただいく぀かのこずに぀いお䞍平を蚀っおいたす。 構文的に正しくないプログラムを䜜成するず、すぐに゚ラヌが発生したす。 関数ではない䜕かの呌び出しや未定矩倉数のプロパティぞのアクセスなど、その他の゚ラヌは、プログラムの実行䞭にこのような意味のない状況に遭遇するず発生したす。



しかし、倚くの堎合、あなたの無意味な蚈算は単玔にNaN数ではないたたは未定矩を生成したす。 プログラムは、䜕か意味のあるこずを実行しおいるこずを確認しお、楜しく続けたす。 このような架空の倀がすでにいく぀かの関数を通過しおいる堎合、゚ラヌは埌で珟れたす。 ゚ラヌメッセヌゞはたったく発生しない堎合がありたすが、実行結果が正しくない堎合がありたす。 そのような問題の原因を芋぀けるこずは難しい䜜業です。



プログラム内のバグを芋぀けるプロセスは、デバッグず呌ばれたす。



厳栌モヌド



JavaScriptを厳密モヌドにするず、JavaScriptをより厳密にできたす。 このために、「use strict」がファむルの先頭たたは関数の本䜓に曞き蟌たれたす。 䟋



 function canYouSpotTheProblem() { "use strict"; for (counter = 0; counter < 10; counter++) console.log("  "); } canYouSpotTheProblem(); // → ReferenceError: counter is not defined
      
      







通垞、カりンタの前の䟋のように、倉数の前にvarを蚘述するのを忘れるず、JavaScriptは静かにグロヌバル倉数を䜜成しお䜿甚したす。 厳栌モヌドでは、゚ラヌがスロヌされたす。 ずおも䟿利です。 ただし、グロヌバル倉数が既に存圚する堎合ぱラヌは発生したせん-割り圓おが新しい倉数を䜜成する堎合のみです。



別の倉曎-このバむンディングには、メ゜ッドずしおではなく呌び出された関数に未定矩が含たれおいたす。 非厳密モヌドで関数を呌び出すずき、これはグロヌバルスコヌプオブゞェクトを指したす。 したがっお、誀っおストリクトモヌドでメ゜ッドを誀っお呌び出した堎合、JavaScriptから䜕かを読み取ろうずするず゚ラヌがスロヌされ、グロヌバルオブゞェクトでうたく動䜜したせん。



たずえば、新しいキヌワヌドなしでコンストラクタヌを呌び出すコヌドを考えたす。この堎合、䜜成されるオブゞェクトを参照したせん。



 function Person(name) { this.name = name; } var ferdinand = Person(""); // - console.log(name); // → 
      
      







無効なPerson呌び出しは成功したすが、未定矩ずしお戻り、グロヌバル倉数名を䜜成したす。 厳栌モヌドでは、すべおが異なりたす。



 "use strict"; function Person(name) { this.name = name; } // ,    'new' var ferdinand = Person(" "); // → TypeError: Cannot set property 'name' of undefined
      
      







゚ラヌに぀いおすぐに通知されたす。 ずおも快適です。



厳密モヌドでは、他のこずができたす。 同じ名前の耇数のパラメヌタヌを䜿甚しお関数を呌び出すこずを犁止し、蚀語の朜圚的に問題のあるプロパティをいく぀か削陀したすたずえば、withステヌトメントは、本曞では説明しおいたせん。



芁するに、プログラムテキストの前に厳密なラベルを䜿甚するず、問題が発生するこずはほずんどありたせんが、問題を確認するのに圹立ちたす。



テスト䞭



蚀語が゚ラヌの発芋に圹立たない堎合、プログラムを起動し、それが本来の方法で䜕かを行うかどうかを芳察するこずにより、゚ラヌを困難な方法で探す必芁がありたす。



䜕床も䜕床も手動で行うこずは、確実に倢䞭になる方法です。 幞いなこずに、倚くの堎合、メむンプログラムの怜蚌を自動化する別のプログラムを䜜成できたす。



䟋ずしお、再びベクタヌタむプを䜿甚したす。



 function Vector(x, y) { this.x = x; this.y = y; } Vector.prototype.plus = function(other) { return new Vector(this.x + other.x, this.y + other.y); };
      
      







ベクタヌの実装が正垞に機胜するこずを確認するプログラムを䜜成したす。 次に、実装を倉曎するたびに、テストプログラムを実行しお、問題が発生しないこずを確認したす。 ベクタヌタむプに機胜たずえば、新しいメ゜ッドを远加するず、この新しい機胜のチェックが远加されたす。



 function testVector() { var p1 = new Vector(10, 20); var p2 = new Vector(-10, 5); var p3 = p1.plus(p2); if (p1.x !== 10) return ": x property"; if (p1.y !== 20) return " : y property"; if (p2.x !== -10) return " : negative x property"; if (p3.x !== 0) return " : x from plus"; if (p3.y !== 25) return " : y from plus"; return " "; } console.log(testVector()); // →  
      
      







このようなチェックを蚘述するず、コヌドが重耇したす。 幞いなこずに、小切手を曞くために特別に調敎された特別な蚀語を䜿甚しおテストスむヌトを曞くのを助ける゜フトりェア補品がありたす。 それらはテストフレヌムワヌクず呌ばれたす。



デバッグ



プログラムの問題に気づいたら-それは正しく動䜜せず、゚ラヌを発行したす-それは問題が䜕であるかを芋぀ける時です。



時々これは明らかです。 ゚ラヌメッセヌゞはプログラムの特定の行に぀ながりたす。゚ラヌの説明ずこの行を読むず、問題を芋぀けるこずができたす。



しかし、垞にではありたせん。 ゚ラヌに぀ながる行は、他の堎所で受け取った䞍正な倀が誀っお䜿甚される最初の堎所であるこずが刀明する堎合がありたす。 ゚ラヌメッセヌゞがたったく衚瀺されない堎合もありたす-単に誀った結果が衚瀺されるだけです。 前の章の挔習を行った堎合、そのような状況にいるこずは間違いないでしょう。



次の䟋では、指定された番号システムの番号を文字列に倉換し、最埌の桁を取埗しお陀算を行い、この番号を取り陀きたす。 しかし、プログラムに゚ラヌが存圚するこずを瀺唆しおいるため、プログラムによっお生成されるワむルドな結果です。



 function numberToString(n, base) { var result = "", sign = ""; if (n < 0) { sign = "-"; n = -n; } do { result = String(n % base) + result; n /= base; } while (n > 0); return sign + result; } console.log(numberToString(13, 10)); // → 1.5e-3231.3e-3221.3e-3211.3e-3201.3e-3191.3e-3181.3

      
      







問題を芋぀けたずしおも、ただ芋぀けおいないふりをしたす。 プログラムがクラッシュするこずはわかっおいるので、その理由を調べる必芁がありたす。



ここでは、コヌドにランダムな倉曎を加えるずいう衝動を克服する必芁がありたす。 代わりに考えおください。 結果を分析し、これが起こる理論を考え出したす。 理論をテストするために远加の芳察を行いたす—理論がない堎合は、理論を発明するのに圹立぀芳察を行いたす。



耇数のconsole.log呌び出しを戊略的な堎所に配眮するこずは、プログラムの機胜に関する詳现情報を取埗するための良い方法です。 この堎合、13、1、0の倀を取るためにnが必芁です。ルヌプの先頭に倀を出力したしょう。



 13 1.3 0.13 0.013 
 1.5e-323
      
      







うん。 13を10で陀算しおも敎数は生成されたせん。 n / = baseの代わりに、n = Math.floorn / baseが必芁です。その堎合、数倀は右に正しく「シフト」されたす。



console.logに加えお、ブラりザヌでデバッガヌを䜿甚できたす。 最新のブラりザでは、遞択したコヌド行にブレヌクポむントを配眮できたす。 これにより、遞択した行に到達するたびにプログラムが䞀時停止し、倉数の内容を衚瀺できたす。 プロセスはブラりザごずに異なるように構成されおいるため、プロセスの詳现に぀いおは説明したせん。ブラりザの「開発者ツヌル」、開発者ツヌルを探しおください。 ブレヌクポむントを蚭定するもう1぀の方法は、デバッガヌキヌワヌドで構成されるコヌドにデバッガヌ呜什を含めるこずです。 開発者ツヌルがアクティブな堎合、プログラムはこの指瀺で䞀時停止され、プログラムのステヌタスを調べるこずができたす。



゚ラヌ䌝播



残念ながら、プログラマはすべおの問題の発生を防ぐこずができたせん。 プログラムが倖郚ず通信する堎合、誀った入力デヌタを受信するか、察話しようずしおいるシステムが壊れおいるか、アクセスできない可胜性がありたす。



単玔なプログラム、たたはあなたの監督の䞋で動䜜するプログラムは、そのような瞬間に単に「あきらめる」こずができたす。 問題を調査しお、再詊行できたす。 「実際の」アプリケヌションは、単に「クラッシュ」するべきではありたせん。 時には、誀った入力デヌタを受け入れお、䜕らかの方法でそれらを操䜜する必芁がありたす。 それ以倖の堎合は、䜕かがうたくいかなかったこずをナヌザヌに䌝える必芁がありたす-そしお、あきらめたす。 いずれにせよ、プログラムは問題に察応しお䜕かをしなければなりたせん。



敎数を芁求しおそれを返すpromptInteger関数があるずしたす。 ナヌザヌが「オレンゞ」ず入力した堎合、圌女はどうすればよいですか



1぀のオプションは、特別な意味を返すこずです。 通垞、これらの目的にはnullおよびundefinedが䜿甚されたす。



 function promptNumber(question) { var result = Number(prompt(question, "")); if (isNaN(result)) return null; else return result; } console.log(promptNumber("  ?"));
      
      







これは信頌できる戊略です。 ここで、promptNumberを呌び出すコヌドは、番号が返されたかどうかを確認する必芁がありたす。返されなかった堎合は、どうにかしお状況から抜け出したす。もう䞀床尋ねるか、デフォルト倀を蚭定したす。 たたは、呌び出した人に特別な意味を返し、倱敗を報告したす。



そのような倚くの堎合、゚ラヌが頻繁に発生し、関数呌び出しコヌドがそれらを考慮する必芁がある堎合、゚ラヌのむンゞケヌタずしお特別な倀を返すこずは完党に受け入れられたす。 しかし、欠点もありたす。 たず、関数がずにかくどんなタむプの倀も返すこずができたらどうでしょうか 圌女が容認できる結果ずは異なる特別な倀を芋぀けるこずは困難です。



2番目の問題-特別な倀を䜿甚するず、コヌドが散らかるこずがありたす。 promptNumber関数が10回呌び出された堎合、10回チェックしお、nullを返したかどうかを確認する必芁がありたす。 nullに察する反応が、nullをより高いレベルに返すこずである堎合、このコヌドが呌び出された堎所では、nullチェックを埋め蟌む必芁もありたす。



䟋倖



関数が正垞に動䜜しない堎合、動䜜を停止し、そのような゚ラヌを凊理できる堎所にゞャンプしたす。 これは䟋倖凊理によっお凊理されたす。



実行時に問題が発生したコヌドは、特定の倀である䟋倖䟋倖の発生、䟋倖のスロヌを発生たたはスロヌできたす。 䟋倖の戻り倀は、関数からの特定の「ポンプされた」戻り倀に䌌おいたす。関数自䜓からだけでなく、それを呌び出したすべおの関数から、実行が開始された堎所にゞャンプしたす。 これは、スタックの巻き戻しず呌ばれたす。 第3章の関数スタックを芚えおいるかもしれたせん...䟋倖は、スタックをすばやくスクロヌルダりンし、発生したすべおの呌び出しコンテキストを砎棄したす。



䟋倖がスタックの最䞋郚にすぐに到達した堎合、それらの利点はほずんどありたせん。 プログラムを爆砎する興味深い方法を提䟛するだけです。 圌らの匷みは、スタックの途䞭で、スタックに沿っおレヌスする䟋倖をキャッチする「障害物」を眮くこずができるこずです。 そしお、これで䜕か有甚なこずができたす。その埌、プログラムは䟋倖がキャッチされたポむントから実行を続けたす。



䟋



 function promptDirection(question) { var result = prompt(question, ""); if (result.toLowerCase() == "left") return "L"; if (result.toLowerCase() == "right") return "R"; throw new Error(" : " + result); } function look() { if (promptDirection("?") == "L") return ""; else return "  "; } try { console.log("  ", look()); } catch (error) { console.log("-  : " + error); }
      
      







throwキヌワヌドは、䟋倖をスロヌするために䜿甚されたす。 catchは、tryブロックにラップされたコヌドで、その埌にcatchが続きたす。 tryブロック内のコヌドが䟋倖をスロヌするず、catchブロックが実行されたす。 括匧で瀺された倉数は、䟋倖の倀にバむンドされたす。 catchブロックの実行が完了した埌、たたはtryブロックが問題なく実行された堎合、実行はtry / catchステヌトメントの埌にあるコヌドに進みたす。



この堎合、Errorコンストラクタヌを䜿甚しお䟋倖を䜜成したした。 これは、メッセヌゞプロパティを持぀オブゞェクトを䜜成する暙準コンストラクタです。 最新のJavaScript環境では、このコンストラクタヌのむンスタンスは、䟋倖がスロヌされたずきに蓄積された呌び出しスタックに関する情報、いわゆるスタックトレヌスも収集したす。 この情報はスタックプロパティに栌玍され、問題の解析に圹立ちたす。問題が発生した関数ず、この呌び出しに぀ながった他の関数を報告したす。



look関数は、promptDirectionの問題の可胜性を完党に無芖するこずに泚意しおください。 これは䟋倖の利点です。゚ラヌ凊理コヌドは、゚ラヌが発生し、凊理される堎所でのみ必芁です。 䞭間関数は単にそれに泚意を払っおいたせん。



たあ、ほずんど。



䟋倖でクリヌンアップ



次の状況を想像しおください。withContext関数は、実行䞭に最䞊䜍の倉数コンテキストが特別なコンテキスト倀を受け取るこずを確認したいず考えおいたす。 完了埌、叀い倀を埩元したす。



var context = null;



 function withContext(newContext, body) { var oldContext = context; context = newContext; var result = body(); context = oldContext; return result; }
      
      







body関数が䟋倖をスロヌした堎合はどうなりたすか この堎合、withContextの呌び出しはスタックからの䟋倖によっおスロヌされ、コンテキスト倉数は元の倀を返したせん。



ただし、tryステヌトメントには別の機胜がありたす。 catchの代わりに、たたはcatchず䞀緒に、finallyブロックを続けるこずができたす。 finallyブロックは、「tryブロックが実行された埌でもコヌドを実行する」こずを意味したす。 関数をクリヌンアップする必芁がある堎合は、クリヌンアップコヌドをfinallyブロックに含める必芁がありたす。



 function withContext(newContext, body) { var oldContext = context; context = newContext; try { return body(); } finally { context = oldContext; } }
      
      







bodyの呌び出し結果を返すために別の倉数に栌玍する必芁がなくなったこずに泚意しおください。 tryブロックから戻っおも、finallyブロックは実行されたす。 これで安党にこれを行うこずができたす



 try { withContext(5, function() { if (context < 10) throw new Error("  !"); }); } catch (e) { console.log(": " + e); } // → : Error:   ! console.log(context); // → null
      
      







withContextから呌び出された関数が「壊れた」ずいう事実にもかかわらず、withContext自䜓はコンテキスト倉数の倀をクリアしたす。



遞択的䟋倖キャッチ



䟋倖がスタックの最䞋郚に到達し、誰もキャッチしおいない堎合、環境はそれを凊理したす。 正確に-特定の環境に䟝存したす。 ブラりザヌでは、゚ラヌの説明がコン゜ヌルに衚瀺されたす通垞は[ツヌル]たたは[開発]メニュヌで利甚できたす。



プログラムが原則ずしお凊理できない゚ラヌたたは問題に぀いお話しおいる堎合は、そのような゚ラヌを単にスキップしおもかたいたせん。 未凊理の䟋倖は、プログラムの問題を報告するための合理的な方法です。最新のブラりザヌのコン゜ヌルは、問題が発生した時点でスタックにあった関数呌び出しに関する必芁な情報を提䟛したす。



問題の発生が予枬可胜な堎合、プログラムは未凊理の䟋倖でクラッシュするこずはありたせん-これは非垞にナヌザヌフレンドリヌではありたせん。



蚱容されない蚀語の䜿甚—存圚しない倉数ぞの参照、nullに等しい倉数のプロパティのク゚リ、たたは関数ではない䜕かの呌び出しも䟋倖をスロヌしたす。 このような䟋倖は、独自の䟋倖ず同じ方法でキャッチできたす。



catchブロックに入るず、tryブロック内の䜕かが䟋倖を匕き起こしたこずがわかるだけです。 䜕が正確に、どのような䟋倖が発生したのかはわかりたせん。



JavaScript露骚な省略は、䟋倖を遞択的にキャッチするための盎接的なサポヌトを提䟛したせんすべおをキャッチするか、たったくキャッチしたせん。 このため、人々はしばしば、発生した䟋倖がcatchブロックがたさに曞かれたものであるず仮定したす。



しかし、異なる堎合がありたす。 違反は別の堎所で発生したか、゚ラヌがプログラムに䟵入したした。 有効な回答が埗られるたでpromptDirectionを呌び出そうずする䟋を次に瀺したす。



 for (;;) { try { var dir = promtDirection("?"); // ← ! console.log("  ", dir); break; } catch (e) { console.log(" .   ."); } }
      
      







for;;コンストラクトは、無限ルヌプを配眮する方法です。 蚱容できる方向に到達した堎合にのみ脱萜したす。 しかし、promptDirectionずいう名前のスペルを間違えたした。これにより、「undefined variable」ずいう゚ラヌが発生したす。 たた、catchブロックは䟋倖eの倀を無芖するため、別の問題を凊理しおいるず仮定しお、スロヌされた䟋倖は誀った入力の結果であるず芋なしたす。 これにより、無限ルヌプが発生し、無効な倉数名に関する有甚な゚ラヌメッセヌゞが非衚瀺になりたす。



原則ずしお、どこかにリダむレクトするずいう目暙がない限り、このような䟋倖をキャッチしないでください。たずえば、ネットワヌクを介しお、プログラムのクラッシュに぀いお別のシステムに通知したす。 さらに、重芁な情報が隠されおいるかどうかを泚意深く確認しおください。



そのため、特定の䟋倖をキャッチする必芁がありたす。 catchブロックで、発生した䟋倖が関心のある䟋倖であるかどうかを確認し、そうでない堎合は再床スロヌしたす。 しかし、どのように䟋倖を認識するのでしょうか



もちろん、メッセヌゞプロパティを、埅機しおいる゚ラヌメッセヌゞず比范できたす。 しかし、これはコヌドを蚘述するための信頌性の䜎い方法です-゜フトりェア意思決定を行うために人メッセヌゞを察象ずした情報を䜿甚したす。 誰かがこのメッセヌゞを倉曎たたは翻蚳するずすぐに、コヌドは機胜しなくなりたす。



新しいタむプの゚ラヌを定矩し、instanceofを䜿甚しお認識しおみたしょう。



 function InputError(message) { this.message = message; this.stack = (new Error()).stack; } InputError.prototype = Object.create(Error.prototype); InputError.prototype.name = "InputError";
      
      







プロトタむプはError.prototypeを継承しおいるため、InputErrorタむプのオブゞェクトに察しおinstanceof Errorも実行されたす。 そしお、他の暙準タむプの゚ラヌError、SyntaxError、ReferenceErrorなどず同様に、nameプロパティが割り圓おられたす。



スタックプロパティを割り圓おるず、Errorオブゞェクトを䜜成し、そのスタックを䜿甚するこずにより、それをサポヌトするプラットフォヌムで、このオブゞェクトにスタックトラッキングを枡そうずしたす。



珟圚、promptDirectionはこのような゚ラヌを䜜成できたす。



 function promptDirection(question) { var result = prompt(question, ""); if (result.toLowerCase() == "left") return "L"; if (result.toLowerCase() == "right") return "R"; throw new InputError("Invalid direction: " + result); }       . for (;;) { try { var dir = promptDirection("?"); console.log(" ", dir); break; } catch (e) { if (e instanceof InputError) console.log(" .   ."); else throw e; } }
      
      







このコヌドはInputErrorむンスタンスのみをキャッチし、他の䟋倖をスキップしたす。 同じタむプミスを再床行うず、未定矩の倉数に関するメッセヌゞが正しく衚瀺されたす。



アサヌション



クレヌムは、単玔な゚ラヌチェックのためのツヌルです。 ヘルパヌ関数のアサヌトを怜蚎しおください。



 function AssertionFailed(message) { this.message = message; } AssertionFailed.prototype = Object.create(Error.prototype); function assert(test, message) { if (!test) throw new AssertionFailed(message); } function lastElement(array) { assert(array.length > 0, "   lastElement"); return array[array.length - 1]; }
      
      







これは、倀の芁件を厳しくするコンパクトな方法で、指定された条件が満たされない堎合に䟋倖をスロヌしたす。 たずえば、配列の最埌の芁玠を取埗するlastElement関数は、アサヌションを䜿甚しなかった堎合、空の配列に察しおundefinedを返したす。空の配列の最埌の芁玠を取埗しおも意味がありたせん。これは明らかにプログラマヌの゚ラヌになりたす。



ステヌトメントは、゚ラヌがコミットされた堎所でプログラムの䞭断を匕き起こすこずを確認する方法であり、システムを介しお送信され、これに関連しない他の堎所で問題を匕き起こすだけでなく、奇劙な量を䞎えたす。



たずめ



゚ラヌず無効な入力は人生で起こりたす。プログラムの゚ラヌを探しお修正する必芁がありたす。自動怜蚌システムを䜿甚しお、プログラムにステヌトメントを远加するこずで、簡単に芋぀けるこずができたす。



あなたのプログラムにない䜕かによっお匕き起こされた問題は、尊厳をもっお扱われなければなりたせん。問題がロヌカルで解決できる堎合、そのようなケヌスを远跡するために特別な倀を返すこずが蚱可される堎合がありたす。他の堎合には、䟋倖を䜿甚するこずが望たしいです。



䟋倖をスロヌするず、try / catchブロックが怜出されるたで、たたはスタックの䞀番䞋に達するたでスタックが巻き戻されたす。䟋倖の倀は、catchブロックに枡されたす。これにより、この䟋倖が実際に埅機しおいるものであるこずを確認しお凊理できたす。プログラムストリヌム内の予枬䞍可胜なむベントを凊理するには、finallyブロックを䜿甚しお、コヌドの特定の郚分がどのような堎合でも実行されるようにしたす。



挔習



リプレむ


50の堎合に2぀の数倀を乗算し、他の堎合にはMultiplicatorUnitFailure型の䟋倖をスロヌする関数primitiveMultiplyがあるずしたす。これをラップする関数を䜜成し、成功する結果が埗られるたで単玔に呌び出したす。



必芁な䟋倖のみを凊理するようにしおください。



 function MultiplicatorUnitFailure() {} function primitiveMultiply(a, b) { if (Math.random() < 0.5) return a * b; else throw new MultiplicatorUnitFailure(); } function reliableMultiply(a, b) { //   } console.log(reliableMultiply(8, 8)); // → 64
      
      







ロックボックス


そのようなかなり䞍自然なオブゞェクトを考えおみたしょう



 var box = { locked: true, unlock: function() { this.locked = false; }, lock: function() { this.locked = true; }, _content: [], get content() { if (this.locked) throw new Error("!"); return this._content; } };
      
      







これはロック付きの箱です。内郚には配列がありたすが、ボックスがロックされおいない堎合にのみ到達できたす。_contentプロパティに盎接アクセスするこずはできたせん。



ボックスのロックを解陀し、機胜を実行し、終了する前にボックスを再床ロックする関数を匕数ずしお取る関数withBoxUnlockedを蚘述したす。枡された関数が正しく実行されたか䟋倖をスロヌしたかは関係ありたせん。



 function withBoxUnlocked(body) { //   } withBoxUnlocked(function() { box.content.push(""); }); try { withBoxUnlocked(function() { throw new Error("  ! !"); }); } catch (e) { console.log(" :", e); } console.log(box.locked); // → true
      
      







ボヌナスゲヌムずしお、withBoxUnlockedを呌び出すずき、ボックスがロックされおいないずきは、ボックスがロックされおいないこずを確認しおください。



All Articles