2011-11-08 21 views
5

Lo siguiente me confunde mucho. Como se señaló en los comentarios, las comparaciones parecen funcionar por sí mismas, pero cuando se juntan noJavascript "==" operador se encuentra

El tiempo debe correr todos los días en el mismo mes, luego incremente i en uno, luego comience nuevamente.

He enlazado toda la secuencia con console.log para tratar de resolverlo, pero no tiene ningún sentido. Todo parece igualarse, pero aún falla la prueba "==" en la sentencia while.

var i=0; 
    var currentdate = 0; 
    var currentmonth = 0; 
    var opensmonth = 0; 
    var opens = [ 
    { "date":"3/30/2006","zip":"30038","latitude":"33.676358","longitude":"-84.15381"}, 
    { "date":"4/31/2006","zip":"30519","latitude":"34.089419","longitude":"-83.94701"} 
    ]; 
    intid = setInterval("stepthrough()", 250); 
    function stepthrough() { 
    //figure out first date. 
    if (currentdate == 0) { // we've not been run before 
     currentdate = opens[0]["date"]; 
     currentmonth = currentdate.split("/", 1); 
     console.log("Current Month: >" + currentmonth +"<"); 
    } 
    console.log("Current month: " + currentmonth + " And opensdate: " + opens[i]["date"].split("/", 1)); 

    // 
    // TWILIGHT ZONE ENTERED. 
    // 
    if (currentmonth == 3) { 
     console.log("Current month equals 3."); // PASSES 
    } 
    if (opens[i]["date"].split("/", 1) == 3) { 
     console.log("Opens date equals 3."); // PASSES 
    } 
    // BOTH THE ABOVE TESTS PASS IN CHROME AND SAFARI WHAT THE F*$K JAVASCRIPT 

    while(opens[i]["date"].split("/", 1) == currentmonth) { // WHY DOESNT THIS WORK I HATE COMPUTERS 
     console.log("Trying to add a point one."); 
     addpoint(i); 
     i++; 
     console.log("Trying to add a point."); 
    } 

    //set the date for next iteration 
    currentdate = opens[i]["date"]; 
    currentmonth = currentdate.split("/", 1); 
    console.log ("Current date is now: " + currentdate + " and current month is now: " + currentmonth); 
    jQuery('div#date').text(currentdate); 

    //if (i>=5000) { 
    if (!opens[i]["date"]) { 
     console.log("Clearing interval"); 
     clearInterval(intid); 
     //jQuery('div#date').text("Limited at 5000 records") 
    } 
    } 
+3

intente utilizar 'parseInt (stringValue, 10)'. –

+0

¿Qué sucede si usa '===' en la línea '// ¿POR QUÉ NO HACE ESTE TRABAJO'? [Esta respuesta] (http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use/359509#359509) sugiere que '==' es malvado y no se puede confiar – CanSpice

+2

Honestamente, no veo una pregunta aquí. –

Respuesta

4

Aquí está el problema: ["1"] == 1 en Javascript, debido a las conversiones implícitas que describe @Matt. Pero ["1"] != ["1"] en Javascript, porque está comparando dos matrices, y por lo tanto dos objetos, y las comparaciones de objetos solo son verdaderas si apuntan al mismo objeto , no si apuntan a dos objetos idénticos.

Cuando asigna con .split('/', 1), obtiene una matriz como ['3'], no la cadena "3" (como creo que podría estar asumiendo). Por lo tanto:

currentmonth = currentdate.split("/", 1); // currentmonth is ["3"] 
currentmonth == 3; // true, as described above 
opens[i]["date"].split("/", 1) == 3; // true, because left-hand evals to ["3"] 
opens[i]["date"].split("/", 1) == currentmonth; 
// false, because you're comparing two arrays - ["3"] != ["3"] 

Para solucionar este problema con su código actual, sólo puede obtener la cadena, no la matriz, así:

currentmonth = currentdate.split("/")[0]; // currentmonth is "3" 
opens[i]["date"].split("/")[0] == currentmonth; // true, both sides are "3" 
+0

Debería haber revisado el resto de las respuestas antes de proceder, simplemente llegué a la misma conclusión. Buena respuesta. – Nicole

+0

He agregado algunos [detalles de los míos] (http://stackoverflow.com/questions/8056317/javascript-operators-lies/8056914#8056914), pero el mérito recae en ti por detectar primero el problema de la matriz. – Nicole

0

¿Puedes probar esto solo para saber si se trata de un entero contra la falla de cadena?

Esta no es una buena solución pero da una pista.

while(opens[i]["date"].split("/", 1) + "str" == currentmonth + "str") 
+1

usaría 'parseInt' en su lugar. –

7

JavaScript está implícito. Esto significa que si cree que intenta tratar algo como un número, lo mejor es tratar ese objeto como un número, incluso si es, digamos, un booleano o una cadena.

Al hacer el estándar ==, JavaScript utilizará las conversiones implícitas para probar y hacer coincidir los tipos. Esto a menudo resulta en resultados de comparación inesperados.

Si desea forzar comparaciones fuertes, debe usar el operador ===.

Dicho esto, si está examinando la representación 'número' de una cadena, p. "123", y quiere usar comparaciones fuertes, debe convertirlo a un número usando parseInt (str, 10);

Para ver algunos ejemplos de tipeo implícito en acción, consulte la respuesta JavaScript truth table.

+0

Buena respuesta, pero en realidad no explica la causa del problema, solo buenas prácticas. – nrabinowitz

+0

'Número' [constructor llamado como una función] (http://stackoverflow.com/questions/2381399/what-is-the-difference-between-new-number-and-number-in-javascript/2381580#2381580) también funciona – Nicole

1

favor Upvote nrabinowitz's answer porque él fue el primero y es correcta.

Sin embargo, yo quiero añadir algunos detalles sobre el problema subyacente y cómo Javascript mangos == conversiones implícitas entre matrices, números y cadenas.

Para resumir: cada tipo tiene reglas ligeramente diferentes cuando se usa == con diferentes tipos. Las matrices se convierten en valores primitivos cuando se comparan con Number o String, pero no cuando se comparan con otra matriz.

Detalle:

  1. String.split devuelve una matriz.
  2. Las cadenas y los números están en bruto types en Javascript. Los otros son Boolean, Object, Null y Undefined.
  3. matriz es de tipo objeto
  4. == sigue la "Abstract equality comparison algorithm" (x == y)
  5. En sus dos primeras comparaciones, ya que uno de los tipos (3) es un número, su condición está bajo la siguiente regla:

    Si Tipo (x) es o bien cadena o Número y Type (y) is Object, devuelve el resultado de la comparación x == ToPrimitive (y).

    En otras palabras, se convierte la matriz ["3"] a 3 y lo compara con 3 — cierto (ver el docs on ToPrimitive)

  6. En el último caso de que se dice que está roto, cae bajo la primera regla, ("Tipo (x) es el mismo que el Tipo (y)" — ambos son objeto Luego se evalúa la siguiente regla:.

    Devuelve true si xey se refieren al mismo objeto. De lo contrario, devuelve falso.

  7. contienen el mismo valor, pero no son lo mismo objeto (cada uno es un diferente resultado de una llamada a String.split), por lo que el resultado es falsa.

Para ilustrar:

console.log("3 == [3]?", 3 == [3]); // true 
console.log("3 == ['3']?", 3 == ['3']); // true 
console.log("'3' == [3]?", "3" == [3]); // true 
console.log("'3' == ['3']?", '3' == ['3']); // true 
console.log("[3] == [3]?", [3] == [3]); // false 
console.log("['3'] == ['3']?", ['3'] == ['3']); // false - NOT SAME OBJECT 

var a = ['3']; 
var b = a; // SAME OBJECT 

console.log("a == b?", a == b); // true! 

La solución, como @nrabinowitz dice, es simplemente añadir [0] al final de la llamada división de manera que el valor es el primer elemento (una cadena) en lugar de la Matriz en sí misma

+0

¡Buen detalle, y gracias por la recomendación upvote! – nrabinowitz