Javascript:什么更有效,IF块或TRY / CATCH?

时间:2009-02-17 22:03:00

标签: javascript try-catch

我对此代码中效率更高的其他一些看法很感兴趣。基本上在下面的代码中,有一个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);

7 个答案:

答案 0 :(得分:19)

例外情况应该用于特殊情况(即您通常不会发生的事情)。通常,您不应该使用异常来捕获可以使用if语句测试的内容。

另外,据我所知,异常比if语句贵得多。

答案 1 :(得分:16)

使用if语句。我不知道TRY / CATCH的开销是多少,但我怀疑它比评估布尔表达式要大得多。要点击TRY / CATCH,你必须:执行一个语句,生成一个错误[带有相关的开销],记录错误(大概),做一个堆栈跟踪(大概),并移回代码。此外,如果您必须调试这些行附近的代码,真正的错误可能会被您的TRY / CATCHing混淆。

此外,它是对TRY / CATCH的误用,并且可能使您的代码更难以阅读。假设您为更长或更多混淆的案例执行此操作?你的捕获物最终会在哪里?

这称为Exception handling

编辑:如下面所述,如果实际导致异常,则仅获取运行时性能命中。

答案 2 :(得分:12)

其他答案都是正确的,try/catch用于特殊情况和错误处理。 if条件适用于程序逻辑。 “哪个更快?”这是一个错误的问题。

一个好的经验法则,如果你对例外没有任何作用,那可能不是例外!

要确定使用哪个,让我们分解你的if条件。

  1. typeof jQuery == 'function'是否定义了jQuery()函数?
  2. typeof nav == 'object' nav全局变量是否包含对象?
  3. typeof pageid != 'undefined'是否定义了pageid全局变量?
  4. typeof document.getElementById('leftnav') == 'object'文档是否包含leftnav元素?
  5. 第一个显然是例外。没有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元素检查是否适用。

    最后,我不禁要说这个“功能”正在处理全局变量。您应该将navpageid传递给函数,以保持封装和理智。

答案 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美分,我希望它们是合理的。