我对此代码中效率更高的其他一些看法很感兴趣。基本上在下面的代码中,有一个setInterval循环,我需要在代码在循环中运行之前满足4个要求。所以在第1节中我写了一个if语句检查所有4.工作正常。
然后我切换到只使用try / catch,我想在try {}中执行代码。逻辑是在每个循环期间,将生成异常但针对每个无效条件进行抑制。在所有条件都为真的最后一个循环中,代码执行并清除间隔。
要么有效。我喜欢try / catch方法,因为我需要编写更少的条件代码并担心破坏。但是我担心try / catch的效率非常低,特别是在一个100ms的setInterval()循环中。关于SO的其他聪明人的一些看法是什么?
的try / catch
var intvar = setInterval(function(){
try{
clearInterval(intvar);
jQuery('#'+nav[pageid].t1+'>a').replaceWith(jQuery('<span>'+jQuery('#'+nav[pageid].t1+'>a').text()+'</span>'));
//set display classes for nav
jQuery('#'+nav[pageid].t1).addClass('selected').find('#'+nav[pageid].t2).addClass('subselect'); //topnav
jQuery('#'+nav[pageid].t3).addClass('selected').find('#'+nav[pageid].t4).addClass('subselect'); //leftnav
}catch(err){}
},100);
IF Block
var intvar = setInterval(function(){
if(typeof jQuery == 'function' && typeof nav == 'object' && typeof pageid != 'undefined' && typeof document.getElementById('leftnav') == 'object'){
clearInterval(intvar);
jQuery('#'+nav[pageid].t1+'>a').replaceWith(jQuery('<span>'+jQuery('#'+nav[pageid].t1+'>a').text()+'</span>'));
//set display classes for nav
jQuery('#'+nav[pageid].t1).addClass('selected').find('#'+nav[pageid].t2).addClass('subselect'); //topnav
jQuery('#'+nav[pageid].t3).addClass('selected').find('#'+nav[pageid].t4).addClass('subselect'); //leftnav
}
},100);
答案 0 :(得分:19)
例外情况应该用于特殊情况(即您通常不会发生的事情)。通常,您不应该使用异常来捕获可以使用if语句测试的内容。
另外,据我所知,异常比if语句贵得多。
答案 1 :(得分:16)
使用if语句。我不知道TRY / CATCH的开销是多少,但我怀疑它比评估布尔表达式要大得多。要点击TRY / CATCH,你必须:执行一个语句,生成一个错误[带有相关的开销],记录错误(大概),做一个堆栈跟踪(大概),并移回代码。此外,如果您必须调试这些行附近的代码,真正的错误可能会被您的TRY / CATCHing混淆。
此外,它是对TRY / CATCH的误用,并且可能使您的代码更难以阅读。假设您为更长或更多混淆的案例执行此操作?你的捕获物最终会在哪里?
编辑:如下面所述,如果实际导致异常,则仅获取运行时性能命中。
答案 2 :(得分:12)
其他答案都是正确的,try/catch
用于特殊情况和错误处理。 if
条件适用于程序逻辑。 “哪个更快?”这是一个错误的问题。
一个好的经验法则,如果你对例外没有任何作用,那可能不是例外!
要确定使用哪个,让我们分解你的if条件。
typeof jQuery == 'function'
是否定义了jQuery()函数?typeof nav == 'object'
nav全局变量是否包含对象?typeof pageid != 'undefined'
是否定义了pageid全局变量?typeof document.getElementById('leftnav') == 'object'
文档是否包含leftnav元素?第一个显然是例外。没有jQuery()函数你就没有了。
第二个也是例外。没有导航对象,你不会去任何地方。
第三个是例外。你需要一个pageid来做任何事情。
第四个可能是逻辑。 “只有在存在leftnav元素时才运行此代码”。这很难分辨,因为其余的代码没有引用leftnav元素!只有评论,红旗。所以这可能是编程错误。
所以我可能会这样做(如果我正在屠杀jQuery,请道歉):
var intvar = setInterval(function() {
// If there's no leftnav element, don't do anything.
if( typeof document.getElementById('leftnav') != 'object') {
return;
}
try {
clearInterval(intvar);
jQuery('#'+nav[pageid].t1+'>a')
.replaceWith(jQuery('<span>'+jQuery('#'+nav[pageid].t1+'>a').text()+'</span>'));
//set display classes for nav
jQuery('#'+nav[pageid].t1)
.addClass('selected')
.find('#'+nav[pageid].t2)
.addClass('subselect'); //topnav
jQuery('#'+nav[pageid].t3)
.addClass('selected')
.find('#'+nav[pageid].t4)
.addClass('subselect'); //leftnav
}
catch(err) {
...do something with the error...
}
},100);
...但我确实会检查leftnav元素检查是否适用。
最后,我不禁要说这个“功能”正在处理全局变量。您应该将nav
和pageid
传递给函数,以保持封装和理智。
答案 3 :(得分:2)
我会写下面的代码:
var startTime = (new Date()).getTime();
for (var i=0; i < 1000; ++i) intvar();
var endTime = (new Date()).getTime();
alert("Took " + ((endTime - startTime) / 1000.0) " seconds");
然后我会尝试两个版本的intvar,看看哪个版本运行得更快。我自己这样做,但我没有你做的页面布局,所以我的代码不起作用。
一些风格评论 - 似乎没有必要测试jQuery
是一个函数。如果不是,您的网页可能会搞砸,以至于不运行intvar
代码对您没有帮助。如果您很少期望抛出异常,我会使用try / catch。
答案 4 :(得分:2)
对于提供的示例,您将围绕应该始终运行的代码块包装try / catch(除非发生可怕的事情),使用try / catch是一种很好的形式。你的比喻:你总是测试“天空是蓝色吗?”在你的if语句中,或者你将它包装在try / catch中,只有当天空变为绿色时才会触发它。
如果您正在处理用户提供的输入,或者由于代码中发生其他事情而导致函数不存在的可能性更高,请使用If语句方法。
请记住,如果您没有触发异常,则代码中没有任何展开或回溯。在示例中,catch只会在出现错误(jQuery缺失或某些此类事情)时才会执行,但是if语句方法会对每个单独调用该函数进行评估 - 您不应该做更多的工作而不是必须
答案 5 :(得分:0)
要像其他人一样直接回答这个问题,如果确实存在错误,try..catch可能会更加昂贵。
指出代码中的一些其他错误超出了其他人已经指出的错误:
这两个代码完全不相同。为了解释,即使代码看起来完全相同,但它们却没有。
在if()检查的情况下,执行NONE代码。在异常处理程序的情况下,将执行异常处理程序内的每行代码。那么,如果错误发生在第二行或第三行会发生什么?然后,如果在执行任何条件之前检查条件,您的代码中会发生完全不同的事情。
答案 6 :(得分:0)
除了给出的答案之外,我还想对这个问题添加一些想法。
不可预见的异常,即运行时引发异常,不应使用try ... catch捕获,因为您要读取在控制台中引发的消息。
尝试...如果发生异常,您的应用程序可以在您的应用程序逻辑中预见到异常,并且您希望在执行某些自定义操作时抛出IMO捕获。即您想要描述它是一个例外,并且它不是应用程序逻辑的一部分。
例如,您可以有一个验证用户输入的方法,因此您可以有一个返回布尔值的isValid
方法,在这种情况下,您将使用if ... then。
另一方面,如果您执行某个过程,并且知道会发生某些异常,从而中断了快乐流程,并且您想处理该异常,那么我认为最好抛出一个异常。
作为抽象示例,您可以具有实现一些业务规则的方法。
不必验证每个业务规则的有效性,您可以使用一个自定义Exception,其中包含动态元数据,当违反有效性时,每种方法都可以抛出该动态元数据并适当地处理它们,否则继续执行快乐流程。
这将转换为:
throw new BusinessValidationException(TAG, 'Reason for the validation');
哪个IMO的描述性要比:
if (!checkValidityBusinessRule())
// doSomething
用于一系列业务规则。
对于该示例,我的拙见是该检查不应该首先进行,并且给定的检查在实现该方法时默认为true。
if(typeof jQuery == 'function' && typeof nav == 'object' && typeof pageid != 'undefined' && typeof document.getElementById('leftnav') == 'object')
这意味着您必须声明性地确保给定条件为真,然后再调用具有副作用的给定方法,从而完全不必执行检查。
如果碰巧其中一个条件为假,那么它将向控制台抛出异常,这实际上是您想要的,因为作为开发人员,这意味着您的应用程序逻辑或生命周期中的某些事物已损坏。
我的2美分,我希望它们是合理的。