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

问题描述 投票:17回答:7

我对这段代码中效率更高的其他一些看法很感兴趣。基本上在下面的代码中,有一个setInterval循环,我需要在代码在循环中运行之前满足4个要求。所以在第1节我写了一个if语句检查所有4.工作正常。

然后我切换到只使用try / catch,我想要执行的代码坐在try {}中。逻辑是在每个循环期间,将生成异常但针对每个无效条件进行抑制。在所有条件都为真的最后一个循环中,代码执行并清除间隔。

要么有效。我喜欢try / catch方法,因为我需要编写更少的条件代码并担心破坏。但是我担心try / catch的效率非常低,特别是在一个100ms的setInterval()循环中。关于SO的其他聪明人的一些看法是什么?

试着抓

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块

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);
javascript try-catch
7个回答
16
投票

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

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

这被称为Exception handling

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


19
投票

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

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


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元素?

第一个显然是个例外。没有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传递给函数,以保持封装和你的理智。


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。


2
投票

对于提供的示例,您将围绕应始终运行的代码块包装try / catch(除非发生可怕的事情),使用try / catch是一种很好的形式。你的比喻:你总是测试“天空是蓝色吗?”在你的if语句中,或者你将它包装在try / catch中,只有在天空变为绿色时触发它。

如果您正在处理用户提供的输入,或者由于代码中发生其他事情而导致函数不存在的可能性更高,请使用If语句方法。

请记住,如果您没有触发异常,则代码中没有任何展开或回溯。在示例中,catch只会在出现错误(jQuery缺失或某些此类事情)时才会执行,但是if语句方法会对每个单独调用该函数进行评估 - 您不应该做更多的工作而不是必须。


0
投票

要像其他人一样直接回答这个问题,如果确实存在错误,try..catch可能会更昂贵。

指出代码中的一些额外错误超出了其他人已经指出的错误:

这两个代码完全不相同。要解释一下,即使代码看起来完全一样,但他们却没有。

在if()检查的情况下,执行NONE代码。在异常处理程序的情况下,将执行异常处理程序内的每行代码。那么,如果错误发生在第二行或第三行会发生什么?然后,如果在执行任何条件之前检查条件,那么代码中会发生完全不同的事情。


0
投票

除了给出的答案,我想在这个问题上添加一些想法。

不可预见的异常,即运行时抛出异常,不应该用try ... catch捕获,因为你想要读取控制台中抛出的消息。

尝试...当应用程序可以在您的应用程序逻辑中预见到并且您希望在执行某些自定义操作时发生异常时,应该抛出IMO。即你希望描述它是一个例外,它不是应用程序逻辑的快乐流程的一部分。

例如,您可以使用一个验证用户输入的方法,这样您就可以使用返回布尔值的isValid方法,在这种情况下,您将使用if ... then。

另一方面,如果您执行某个进程,并且您知道可能发生某个异常会中断快乐流并且您想要处理此异常,我觉得抛出异常会更好。

作为抽象示例,您可以使用实现某些业务规则的方法。 您可以使用一个包含动态元数据的自定义异常,而不是验证每个业务规则的有效性,这些异常可以在违反有效性时由这些方法抛出并适当地处理它们,否则继续开心流程。 这将转化为:

throw new BusinessValidationException(TAG, 'Reason for the validation');

哪个IMO比以下内容更具描述性:

if (!checkValidityBusinessRule()) 
    // doSomething 

对于一系列业务规则。

至于这个例子,我的拙见认为,这个检查不应该首先发生,并且默认情况下给定的检查是真的,以实现该方法。

if(typeof jQuery == 'function' && typeof nav == 'object' && typeof pageid != 'undefined' && typeof document.getElementById('leftnav') == 'object')

这意味着在调用具有副作用的给定方法之前,必须声明性地确保给定条件为真,从根本不需要执行检查。 如果碰巧其中一个条件是假的,那么它将向控制台抛出异常,这实际上是你想要的,因为作为开发人员,这意味着应用程序逻辑或生命周期中的某些东西被破坏了。

我的2美分,我希望他们有意义。

© www.soinside.com 2019 - 2024. All rights reserved.