关于JS抛出错误使用汇总
在JS中抛出错误是一门艺术。摸清楚代码中哪里合适抛出错误是需要时间的。因此,一旦搞清楚了这一点,调试代码的事件将大大缩短,对代码的满意度将急剧提升。
错误的本质
当某些非期望的事情发生时程序就引发一个错误。也许是给一个函数传递了一个不正确的值,或者是数学运算碰到了一个无效的操作数。编程语言定义了一组基本的规则,当偏离了这些规则时将导致错误,然后开发者能修复代码。如果错误没有被抛出或者报告给你的话,调试是非常困难的。如果所有的失败都是悄无声息的,首要的问题是那必将消耗你大量的时间才能发现它,更不要说单独隔离并修复它了。所以,错误是开发者的朋友,而不是敌人。
错误常常在非期望的地点、不恬当的时机跳出来,这很麻烦。更糟糕的是,默认的错误消息通常太简洁而无法解释到底什么东西出错了。JS错误消息以信息稀少、隐晦含糊而臭名昭著(特别是在老版本的IE中),这只会让问题更加复杂化。想象一下,如果跳出一个错误能这样描述:“由于发生这些情况,该函数调用失败”。那么,调试任务马上就会变得更加简单,这正是抛出自己的错误的好处。
像内置的失败案例一样来考虑错误是非常有帮助的。在代码某个特殊之处计划一个失败总比要在所有的地方都预期失败简单的多。在产品设计上,这是非常普遍的实践经验,而不仅仅是在代码编写方面。汽车尚有碰撞力吸收区域,这些区域框架的设计旨在撞击发生时以可预测的方式崩塌。知道一个碰撞到来时这些框架将如何反应——特别是,哪些部分将失败——制造商将能保证乘客的安全。你的代码也可以用这种方法来创建。
在JS中抛出错误
毫无疑问,在JS中抛出错误要比在任何其他语言中做同样的事情更加有价值,这归咎于Web端调试的复杂性。可以使用throw操作符,将提供的一个对象作为错误抛出。任何类型的对象都可以作为错误抛出,然而,Error对象是最常用的。
throw new Error('Something bad happened.');
内置的Error类型在所有的JS实现中都是有效的,它的构造器只接受一个参数,指代错误消息(message)。当以这种方式抛出错误时,如果没有通过try-catch语句来捕获的话,浏览器通常直接显示该消息(message字符串)。当今大多数浏览器都有一个控制台(console),一旦发生错误都会在这里输出错误信息。换言之,任何你抛出的和没抛出的错误都被以相同的方式来对待。
缺乏经验的开发者有时直接将一个字符串作为错误抛出,如:
// 不好的写法throw 'message';
这样做确实能够抛出一个错误,但不是所有的浏览器做出的响应都会按照你的预期。Firefox、Opera和Chrome都将显示一条“uncaught exception”消息,同时它们包含上述消息字符串。Safari和IE只是简陋地抛出一个“uncaught exception”错误,完全不提供上述消息字符串,这种方式对调试无益。
显然,如果愿意,你可以抛出任何类型的数据。没有任何规则约束不能是特定的数据类型。
throw { name: 'Nicholas' };throw true;throw 12345;throw new Date();
就一件事情需要牢记,如果没有通过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)。类库提供了对脏的实现细节的抽象,目的是让开发者用得更爽。抛出错误有助于对开发者安全地隐藏这些脏的实现细节。
这里有一些关于抛出错误很好的经验法则:
一旦修复了一个很难调试的错误,尝试增加一两个自定义错误。当再次发生错误时,这将有助于更容易地解决问题。
如果正在编写代码,思考一下:“我希望[某些事情]不会发生,如果发生,我的代码会一团糟糕”。这时,如果“某些事情”发生,就抛出一个错误。
如果正在编写的代码别人(不知道是谁)也会使用,思考一下他们使用的方式,在特定的情况下抛出错误。
请牢记,我们目的不是防止错误,而是在错误发生时能更加容易地调试。
相信看了本文案例你已经掌握了方法,更多精彩请关注其它相关文章!
推荐阅读:
以上就是关于JS抛出错误使用汇总的详细内容,更多请关注其它相关文章!
上一篇: jQuery实现鼠标可拖动调整表格列宽度_jquery
下一篇: PHP中多张图片合成一张图片例子
推荐阅读
-
关于使用JS获取浏览器类型的方法
-
windows下关于sublime text2,HTML/CSS/JS Prettify插件使用路径问题处理
-
详解Vue.js使用Swiper.js在iOS<11时出现错误
-
jQuery中关于ScrollableGridPlugin.js(固定表头)插件的使用逐步解析
-
使用Webpack提高Vue.js应用的方式汇总(四种)
-
react框架下,在页面内加载显示PDF文件,关于react-pdf-js的使用注意事项
-
js 关于apply和call的理解使用
-
关于js的三种使用方式(行内js、内部js、外部js)的程序代码
-
关于使用JS获取浏览器类型的方法
-
详解Vue中使用v-for语句抛出错误的解决方案