2009-02-17 31 views
14

Me gustaría algunas otras opiniones sobre qué es más eficiente en este código. Básicamente, en el siguiente código, hay un loop setInterval y necesito que 4 requisitos sean verdaderos antes de que el código se ejecute en el ciclo. Entonces, en v.1, escribí una declaración if que verificaba 4. Funcionó bien.Javascript: ¿Qué es más eficiente, bloque IF o TRY/CATCH?

Luego cambié a simplemente usar try/catch, con el código que quiero ejecutar sentado en try {}. La lógica era que durante cada ciclo, se generaba una excepción pero se suprimía para cada condición inválida. En el ciclo final donde todas las condiciones son verdaderas, el código se ejecuta y borra el intervalo.

Cualquiera de los dos funciona. Me gusta el método try/catch porque hay menos código condicional que necesito escribir y me preocupa romper. Pero me preocupa que try/catch sea realmente ineficiente, especialmente en un loop setInterval() que alcanza los 100 ms. ¿Cuáles son algunas opiniones de otras mentes brillantes aquí en 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); 

Si el bloque

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

Respuesta

15

Usa la instrucción if. No sé cuál es la sobrecarga para un TRY/CATCH, pero sospecho que es mucho mayor que evaluar una expresión booleana. Para presionar TRY/CATCH tendrá que: ejecutar una declaración, generar un error [con esa sobrecarga asociada], registrar el error (presumiblemente), hacer una stacktrace (presumiblemente) y regresar al código. Además, si tiene que depurar el código cerca de esas líneas, el error real podría ofuscarse con lo que está TRY/CATCHing.

Además, es un uso indebido de TRY/CATCH y puede hacer que su código sea mucho más difícil de leer. ¿Suponga que hace esto por casos más largos o más ofuscados? ¿Dónde podría terminar tu captura?

Esto se conoce como Exception handling

EDIT: Como se ha comentado a continuación, sólo se toma el impacto en el rendimiento en tiempo de ejecución si en realidad provocar una excepción.

+0

Solo para agregar a esto, el costo de la prueba/captura es cuando se lanza una excepción, de lo contrario es insignificante. Por lo tanto, si puede probar de manera confiable la condición (y evitar la excepción) con un if si es más eficiente. –

+0

No sé sobre JavaScript, pero hasta donde yo sé, un bloque try empuja algunas cosas en la pila. Un bloque de prueba dentro de un circuito cerrado lo haría mucho más lento que un bloque de prueba fuera del circuito. ¿Es de alguna manera diferente en JavaScript? –

16

Las excepciones deben ser utilizados para circunstancias excepcionales (es decir, lo que no se espera que ocurra en circunstancias normales). En general, no debe usar excepciones para detectar algo que pueda probar con una instrucción if.

Además, por lo que entiendo, las excepciones son mucho más caras que las declaraciones if.

+5

Completamente en desacuerdo con esta afirmación más bien audaz. P.ej. en Python ['try except' is preferred] (http://stackoverflow.com/questions/1835756/using-try-vs-if-in-python) Además, decir que algo es" costoso ", algunos datos serían buenos . De nuevo, en Python ["si" es más "caro"] (http://stackoverflow.com/a/3929887/1167879). –

+1

Por supuesto, el OP preguntaba por Javascript, no por Python. Además, es posible que desee leer el enlace que proporcionó. Dice esencialmente lo mismo que cdmckay: Use excepciones para condiciones excepcionales. – JAB

+0

@AlexOkrushko La filosofía de EAFP, más fácil de pedir perdón que permiso, es adoptada por la comunidad de Python no js. –

2

que iba a escribir el siguiente código:

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

Entonces me gustaría probar ambas versiones de IntVar y ver que se ejecuta con mayor rapidez. Lo haría yo mismo, pero no tengo el diseño de página que haces para que mi código no funcione.

Algunos comentarios estilísticos: no parece necesario probar que jQuery es una función. Si no es así, es probable que su página web esté en mal estado, por lo que no ejecutar el código intvar no lo ayudará. Si rara vez espera que se emitan las excepciones, usaría el try/catch.

2

Para el ejemplo provisto en el que está envolviendo un try/catch alrededor de un bloque de código que siempre debe ejecutarse de todos modos (a menos que ocurra algo horrible), es una buena forma de usar try/catch. Una analogía para ti: siempre pruebas "¿Es azul el cielo?"en su sentencia if, o lo envolvería en un try/catch que se activa solo cuando el cielo pasa a verde.

Use el método de declaración If si está tratando con la entrada proporcionada por el usuario o si las posibilidades de una función que no existe es mucho más alta debido a que algo más está sucediendo en el código.

Tenga en cuenta que si no desencadena la excepción, no tiene ningún desenrollado o retroceso en el código. En el ejemplo, la captura ejecute solo si algo está mal (falta jQuery o algo por el estilo), sin embargo, el método de declaración if tiene una evaluación en CADA LLAMADA INDIVIDUAL para esa función: no debe hacer más trabajo del que debe.

10

Las otras respuestas son correctas, try/catch es por circunstancias excepcionales y manejo de errores. if las condiciones son para la lógica del programa. "¿Cual es mas rápido?" es la pregunta equivocada

Una buena regla general, si no hace nada con la excepción, ¡probablemente no sea la excepción!

Para averiguar qué usar, analicemos su condición si.

  1. typeof jQuery == 'function' ¿Está definida la función jQuery()?
  2. typeof nav == 'object' ¿La variable global nav contiene un objeto?
  3. typeof pageid != 'undefined' ¿Está definida la variable global pageid?
  4. typeof document.getElementById('leftnav') == 'object' ¿El documento contiene un elemento leftnav?

La primera es claramente una excepción. No está llegando lejos sin una función jQuery().

La segunda también es una excepción. No irás a ningún lado sin un objeto de navegación.

El tercero es una excepción. Necesitas un pageid para hacer cualquier cosa.

El cuarto es probablemente la lógica. "Solo ejecuta este código si hay un elemento leftnav". ¡Es difícil de decir porque el resto del código no hace referencia a un elemento leftnav! Solo los comentarios, una bandera roja. Entonces, probablemente sea un error de programación.

Así que probablemente haría esto (con disculpas si estoy carnicería 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); 

... pero realmente me examino si el cheque elemento leftnav es aplicable.

Finalmente, no puedo dejar de comentar que esta "función" funciona con variables globales. En su lugar, debe estar pasando nav y pageid en la función para mantener el encapsulamiento y su cordura.

+0

Buen punto, preguntando "¿Qué es una excepción?" – RobW

0

Para responder directamente a la pregunta, como todos los demás, es probable que la try..catch sea más costosa si realmente hay un error.

señalar algunos errores adicionales en el código más allá de lo que otros ya han señalado:

Estos dos códigos no son en absoluto equivalente. Para explicar, a pesar de que los códigos parecen hacer exactamente lo mismo, no lo hacen.

En el caso de la comprobación if(), NINGUNO del código se ejecuta. En el caso del manejador de excepciones, se ejecutará cada línea de código dentro del manejador de excepciones. Entonces, ¿qué pasa si el error ocurre en el segundo, o en la tercera línea? Entonces tienes algo completamente diferente sucediendo en tu código que lo que obtienes si revisas las condiciones antes de ejecutar cualquiera de ellas.

Cuestiones relacionadas