19

我喜欢关于这段代码更有效的一些其他意见。基本上在下面的代码中,有一个 setInterval 循环,在代码在循环中运行之前,我需要满足 4 个要求。所以在 v.1 中我写了一个 if 语句检查所有 4。工作正常。

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

要么工作。我喜欢 try/catch 方法,因为我需要编写的条件代码更少并且担心会破坏。但我担心 try/catch 效率很低,尤其是在 setInterval() 循环达到 100 毫秒时。其他聪明人对 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);

中频块

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);
4

7 回答 7

21

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

另外,据我了解,异常比 if 语句要昂贵得多。

于 2009-02-17T22:07:18.423 回答
18

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

此外,这是对 TRY/CATCH 的误用,会使您的代码更难阅读。假设您对更长或更模糊的情况执行此操作?你的收获会在哪里结束?

这称为异常处理

编辑:如下所述,如果您确实导致异常,您只会受到运行时性能的影响。

于 2009-02-17T22:12:12.467 回答
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进入函数,以保持封装和您的理智。

于 2009-02-18T06:29:48.120 回答
3

我会写下面的代码:

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。

于 2009-02-17T22:07:39.450 回答
2

对于所提供的示例,您将 try/catch 包装在始终应该运行的代码块上(除非发生可怕的事情),使用 try/catch 是一种很好的形式。给你打个比方:你总是测试“天空是蓝色的吗?” 在您的 if 语句中,还是将其包装在仅在天空变为绿色时触发的 try/catch 中。

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

请记住,如果您不触发异常,您就没有跨代码的任何展开或回溯。在示例中,catch 只会在出现错误(缺少 jQuery 或类似的事情)时执行,但是 if 语句方法在每次调用该函数时都会进行评估 - 你不应该做比你必须做的更多的工作.

于 2009-02-17T23:51:03.447 回答
0

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

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

这两个代码根本不等价。解释一下,即使代码看起来做同样的事情,但它们没有。

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

于 2014-04-18T02:28:39.663 回答
0

除了给出的答案,我想就这个主题添加一些想法。

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

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')

What it means is that you must declaratively ensure that given conditions are true before invoking the given method with side-effects, taking away the necessity to perform the checks at all.
If it so happens that one of the conditions is false, then it will throw an exception to the console, which is actually what you want because as a developer it means that something in your application logic or lifecycle is broken.

My 2 cents, I hope they make sense.

于 2019-04-14T15:53:51.047 回答