今回はJSスローの使い方と、JSがエラーをスローする際の注意点についてまとめてみました。実際のケースを見てみましょう。
JS でエラーをスローするのは芸術です。コード内のどこでエラーをスローするのが適切かを判断するには時間がかかります。したがって、これを理解すると、コードのデバッグ時間が大幅に短縮され、コードに対する満足度が大幅に向上します。
エラーの性質
予期せぬことが起こった場合、プログラムはエラーを発生させます。おそらく、不正な値が関数に渡されたか、数学演算で無効なオペランドが検出された可能性があります。 プログラミング言語は基本的なルールを定義しており、これらのルールから逸脱するとエラーが発生し、開発者はコードを修正できます。エラーがスローされない、またはエラーが報告されない場合、デバッグは非常に困難になります。すべての障害が発生しない場合、最初の問題は、障害を切り分けて修正することはおろか、障害を見つけるのに多大な時間がかかることです。したがって、エラーは開発者の敵ではなく味方です。
エラーは予期せぬ場所や不適切なタイミングで発生することが多く、非常に面倒です。さらに悪いことに、デフォルトのエラー メッセージは簡潔すぎて、正確に何が問題になったのかを説明できないことがよくあります。 JS エラー メッセージは (特に古いバージョンの IE で) まばらでわかりにくいことで知られており、これが問題をさらに悪化させます。 「次の条件が発生したため、この関数呼び出しは失敗しました。」というエラーがポップアップ表示された場合を想像してください。そうすれば、デバッグ タスクがすぐに簡単になります。これは、独自のエラーをスローすることの利点です。
エラーを組み込みの失敗ケースのように考えると非常に役立ちます。コード内の特定の場所で障害が発生することを計画する方が、あらゆる場所で障害が発生することを想定するよりもはるかに簡単です。これはコーディングだけでなく、製品設計においても非常に一般的な方法です。車には、衝撃が発生したときにフレームが予測可能な方法で崩れるように設計された衝突吸収領域もあります。衝突が起こったときにこれらのフレームがどのように反応するか、具体的にはどの部品が故障するのかを知ることで、メーカーは乗客の安全を守ることができます。コードもこの方法で作成できます。
JS でのエラーのスロー
Web 側のデバッグは複雑であるため、JS でエラーをスローすることは、他の言語で同じことを行うよりも価値があることは疑いの余地がありません。 throw 演算子を使用して、提供されたオブジェクトをエラーとしてスローできます。任意のタイプのオブジェクトをエラーとしてスローできますが、Error オブジェクトが最も一般的に使用されます。
throw new Error('Something bad happened.');
組み込みの Error 型は、すべての JS 実装で有効です。そのコンストラクターは、エラー メッセージを参照する 1 つのパラメーターのみを受け取ります。この方法でエラーがスローされた場合、try-catch ステートメントでキャッチされない場合、ブラウザは通常、メッセージ (メッセージ文字列) を直接表示します。現在のほとんどのブラウザにはコンソールがあり、エラーが発生するとエラー メッセージが出力されます。つまり、スローしたエラーもスローしなかったエラーも同じように扱われます。
経験の浅い開発者は、次のような文字列をエラーとして直接スローすることがあります:
// 不好的写法throw 'message';
これは実際にエラーをスローする可能性がありますが、すべてのブラウザーが期待どおりに応答するわけではありません。 Firefox、Opera、Chrome はすべて「キャッチされない例外」メッセージを表示し、上記のメッセージ文字列が含まれています。 Safari と IE は、上記のメッセージ文字列をまったく提供せずに、単に「キャッチされない例外」エラーをスローします。これはデバッグには役に立ちません。
もちろん、必要に応じて、あらゆる種類のデータを破棄できます。制約を特定の データ型にすることができないという規則はありません。
throw { name: 'Nicholas' };throw true;throw 12345;throw new Date();
留意すべき点が 1 つあります。投げられた値が try-catch ステートメントでキャッチされない場合は、エラーが発生します。 Firefox、Opera、Chrome はすべて、スローされた値に対して String() 関数を呼び出して、エラー メッセージの表示ロジックを完成させますが、Safari と IE には当てはまりません。すべてのブラウザーにおいて、カスタム エラー メッセージをエラーなく表示する唯一の方法は、Error オブジェクトを使用することです。
エラーをスローする利点
独自のエラーをスローすると、ブラウザーが表示する正確なテキストを使用できます。行番号と列番号に加えて、問題のデバッグに必要な情報を含めることができます。エラー メッセージには、関数名と関数が失敗した理由を常に含めることをお勧めします。次の関数を調べてください:
function getDivs (element) { return element.getElementsByTagName('div'); }
この関数は、element 要素の下にあるすべての子孫要素の中から div 要素を取得するように設計されています。操作対象の関数に渡される DOM 要素に null 値を渡すのが一般的ですが、実際に必要なのは DOM 要素です。この関数に null を渡すとどうなるでしょうか? 「object Expected」のようなあいまいなエラー メッセージが表示されます。次に、実行スタックを調べて、実際にソース ファイル内で問題を特定する必要があります。エラーをスローするとデバッグが簡単になります:
function getDivs (element) { if (element && element.getElementsByTagName) { return element.getElementsByTagName('div'); } else { throw new Error('getDivs(): Argument must be a DOM element.'); } }
现在给getDivs()函数抛出一个错误,任何时候只要element不满足继续执行的条件,就会抛出一个错误明确地陈述发生的问题。如果在浏览器控制台中输出该错误,你马上能开始调试,并知道最有可能导致该错误的原因是调用函数试图用一个值为null的DOM元素去做进一步的事情。
我倾向于认为抛出错误就像给自己留下告诉自己为什么失败的标签。
何时抛出错误
理解了如何抛出错误只是等式的一个部分,另外一部分就是要理解什么时候抛出错误。由于JS没有类型和参数检查,大量的开发者错误地假设他们自己应该实现每个函数的类型检查。这种做法并不实际,并且会对脚本的整体性能造成影响。考察下面的函数,它试图实现充分的类型检查。
// 不好的做法:检查了太多的错误function addClass (element, className) { if (!element || typeof element.className !== 'string') { throw new Error('addClass(): First argument must be a DOM element.'); } if (typeof className !== 'string') { throw new Error('addClass(): Second argument must be a string.'); } element.className += '' + className; }
这个函数本来只是简单地给一个给定的元素增加一个CSS类名(className),因此,函数的大部分工作变成了错误检查。纵然它能在每个函数中检查每个参数(模仿静态语言),在JS中这么做也会引起过度的杀伤。辨识代码中哪些部分在特定的情况下最有可能导致失败,并只在那些地方抛出错误才是关键所在。
在上例中,最有可能引发错误的是给函数传递一个null引用值。如果第二个参数是null或者一个数字或者一个布尔值是不会抛出错误的,因为JS会将其强制转换为字符串。那意味着导致DOM元素的显示不符合期望,但这并不至于提高到严重错误的程度。所以,我只会检查DOM元素。
// 好的写法function addClass (element, className) { if (!element || typeof element.className !== 'string') { throw new Error('addClass(): First argument must be a DOM element.'); } element.className += '' + className; }
如果一个函数只被已知的实体调用,错误检查很可能没有必要(这个案例是私有函数);如果不能提前确定函数会被调用的所有地方,你很可能需要一些错误检查。这就更有可能从抛出自己的错误中获益。抛出错误最佳的地方是在工具函数中,如addClass()函数,它是通用脚本环境中的一部分,会在很多地方使用,更准确的案例是JS类库。
针对已知条件引发的错误,所有的JS类库都应该从它们的公共接口里抛出错误。如jQuery、YUI和Dojo等大型的库,不可能预料你在何时何地调用了它们的函数。当你做错事的时候通知你是它们的责任,因为你不可能进入库代码中去调试错误的原因。函数调用栈应该在进入库代码接口时就终止,不应该更深了。没有比看到由一打库代码中函数调用时发生一个错误更加糟糕的事情了吧,库的开发者应该承担起防止类似情况发生的责任。
私有JS库也类似。许多Web应用程序都有自己专用的内置的JS库或“拿来”一些有名的开源类库(类似jQuery)。类库提供了对脏的实现细节的抽象,目的是让开发者用得更爽。抛出错误有助于对开发者安全地隐藏这些脏的实现细节。
这里有一些关于抛出错误很好的经验法则:
一旦修复了一个很难调试的错误,尝试增加一两个自定义错误。当再次发生错误时,这将有助于更容易地解决问题。
如果正在编写代码,思考一下:“我希望[某些事情]不会发生,如果发生,我的代码会一团糟糕”。这时,如果“某些事情”发生,就抛出一个错误。
如果正在编写的代码别人(不知道是谁)也会使用,思考一下他们使用的方式,在特定的情况下抛出错误。
请牢记,我们目的不是防止错误,而是在错误发生时能更加容易地调试。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上がJS によってスローされるエラーの使用の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。