2010-04-19 6 views
18

Buscando en el núcleo de jQuery me encontré con la siguiente convención código:¿Es restar Zero algún tipo de truco de rendimiento de JavaScript?

nth: function(elem, i, match){ 
    return match[3] - 0 === i; 
}, 

y yo estaba muy curioso sobre el fragmento de match[3] - 0

caza alrededor de '-0' en Google no es demasiado productiva, y una búsqueda de 'menos cero' trae de vuelta una referencia a una canción de Bob Dylan.

Entonces, ¿alguien puede decirme. ¿Es esto algún tipo de truco de rendimiento, o hay una razón para hacer esto en lugar de parseInt o parseFloat?

+1

Hice una pregunta muy similar aquí. Vale la pena buscar en algunas de las respuestas: http://stackoverflow.com/questions/2526682/why-is-javascripts-math-floor-the-slowest-way-to-calculate-floor-in-javascript – z5h

Respuesta

9

Sobre la base de algunas carreras de referencia rápida y sucia, "1234" - 0 fue de un 50% más rápido que parseInt("1234") y un 10% más rápido que +"1234" en Firefox 3.6.

Actualización:

Mi punto de referencia "rápida y sucia" no era muy útil, ya que se acaba de convertir la cadena "1234" en un bucle. Intenté de nuevo usando una lista aleatoria de números, y los resultados están por todo el mapa. Los tres métodos están todos dentro de 400-500 ms en esta computadora, ¡excepto cuando saltan a 1300 ms! Creo que la recolección de basura está interfiriendo.Aquí hay un código para jugar en Firebug, en caso de que hice algo estúpido:

function randomList() { 
    var list = []; 
    for (var i = 0; i < 1000000; i++) { 
     list.push("" + Math.floor(Math.random()*4000000000)); 
    } 
    return list; 
} 

function testParseInt(list) { 
    console.log("Sanity check: parseInt('" + list[0] + "') = " + parseInt(list[0])); 
    var start = new Date(); 
    for (var string in list) 
     var tmp = parseInt(string); 
    var time = new Date() - start; 
    console.log("parseInt(string): " + time); 
} 

function testMinusZero(list) { 
    console.log("Sanity check: '" + list[0] + "' - 0 = " + (list[0] - 0)); 
    var start = new Date(); 
    for (var string in list) 
     var tmp = string - 0; 
    var time = new Date() - start; 
    console.log("string - 0: " + time); 
} 

function testUnaryPlus(list) { 
    console.log("Sanity check: +'" + list[0] + "' = " + (+list[0])); 
    var start = new Date(); 
    for (var string in list) 
     var tmp = +string; 
    var time = new Date() - start; 
    console.log("+string: " + time); 
} 

function testPlusZero(list) { 
    console.log("Sanity check: '" + list[0] + "' + 0 = " + (list[0] + 0) + " Oh no!"); 
    var start = new Date(); 
    for (var string in list) 
     var tmp = string + 0; 
    var time = new Date() - start; 
    console.log("string + 0: " + time); 
} 


var numbers = randomList(); 

testParseInt(numbers); 
testMinusZero(numbers); 
testUnaryPlus(numbers); 
testPlusZero(numbers); 
+3

¿Por qué es así? –

+0

No estoy familiarizado con la implementación, pero supongo que hay una sobrecarga al llamar a la función 'parseInt' (y tiene un comportamiento algo diferente). Como '+' también se utiliza para la concatenación de cadenas, la determinación de su contexto puede ser una fuente de sobrecarga en ese caso. No tengo idea si el rendimiento fue la razón para usar -0, pero es una coincidencia interesante. –

+0

Gracias por tomarse la molestia de hacer esto. Me pregunto si hay alguna diferencia comparativa entre +0 y -0, como se destaca en la publicación de @ S.Mark. –

14

Probablemente sea solo una forma abreviada de forzar el lado izquierdo hacia el número entero. No es tan claro como llamar a una función, por supuesto.

This tutorial on type-conversion estados:

Cualquier operador matemático excepto el operador concatenación/adición se fuerza de tipo de conversión. Así conversión de una cadena en un número podría implicar la realización de una operación matemática en la representación de cadena del número que no afectaría a la número resultante, tales como restar o multiplicar cero a uno.

Esto también revela que "restar" es un término de búsqueda mejor que "menos". :)

+0

Gracias por el enlace –

3

Su principal razón para utilizar esta sintaxis es si tiene código genérico que puede ser cualquier número (int o float) y que desea hacer un tipo sensible a comparar (===)

0

Si se trata de no es una reliquia vieja que se perdió, entonces solo intenta cambiar el tipo a Número.

+0

Me doy cuenta de que cambia un tipo a un número. Esperaba una explicación de por qué se hizo de esta manera. –

0

Realmente parece un "performant" parseInt para mí.

+0

Según mi respuesta, no es 'parseInt', sino' parseFloat' sin ignore-trailing-garbage _ "feature" _. – Phrogz

5

Sólo una información, Según this sitio

utilizando operador unario + es uno más rápido que cualquiera de los siguientes (los cuales Incluye '- 0'):

var numValue = stringValue - 0; 
/* or */ 
var numValue = stringValue * 1; 
/* or */ 
var numValue = stringValue/1; 

unario operador + de tipo convertidos también su operando a un número y porque que no realiza ninguna operación matemática adicional es el método más rápido para convertir un número en un número.

Esto contradice el punto de referencia de James, aunque podría estar en lo cierto. Creo que jQuery no utilizaría esta sintaxis si fuera lenta.

+0

+1 para siendo un sabio unicornio ... – Reigel

+0

+1. "lento" es un término relativo. El punto de referencia de James, aunque es un buen ejemplo "rápido y sucio", se basa únicamente en Firefox. Diferentes implementaciones de JavaScript difieren en sus optimizaciones de rendimiento y lo mismo puede no ser cierto para otros navegadores (solo una forma de averiguarlo realmente). –

10

Diversas formas de coerse cadenas JS para números y sus consecuencias:

Results of converting various strings using the above techniques http://phrogz.net/JS/string_to_number.png

Yo personalmente uso *1 ya que es corto para escribir, pero aún se destaca (a diferencia de la unario +), y, o bien me da lo que escribió el usuario o falla completamente. Solo uso parseInt() cuando conozco que habrá contenido no numérico al final para ignorar, o cuando necesito analizar una cadena que no sea de base-10.

+0

Gracias. ¿Hay alguna métrica sobre el rendimiento relativo de estos? –

+0

Intentaré crear algo. En general, los métodos ('parse *') serán _mensurablemente_ más lentos que los lanzamientos implícitos, pero probablemente no _noticiamente_ más lentos a menos que estés haciendo MUCHAS conversiones de cadena a número. – Phrogz

+0

@JamesWiseman Creé un punto de referencia, pero los resultados generalmente varían demasiado como para informar. Puede probar el punto de referencia aquí: http://phrogz.net/JS/string_to_number.html Vuelva a cargarlo varias veces para ver la variación. – Phrogz

Cuestiones relacionadas