Reputation: 133
The following confuses me greatly. As noted in the comments, the compares seem to work by themselves, but when put together they don't
The while should run for all days in the same month, then increment i by one, then start over again.
I have laced the whole sequence up with console.log to try to figure it out, but it doesn't make any sense. Everything seems to equal one another, but still fails the "==" test in the while statement.
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")
}
}
Upvotes: 4
Views: 223
Reputation: 33227
Please upvote nrabinowitz's answer because he was first and it is correct.
However, I do want to add some details on the underlying problem and how Javascript handles ==
implicit conversions between Arrays, Numbers, and Strings.
To summarize: Each type has slightly different rules when using ==
with different types. Arrays are converted to primitive value when compared to Number or String, but not when compared with another Array.
Detail:
String.split
returns an Array.==
follows the "Abstract equality comparison algorithm" (x == y
)In your first two comparisons, since one of the types (3
) is a Number, your condition falls under the following rule:
If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
In other words, it converts the array ["3"]
to 3 and compares it with 3 — true (see the docs on ToPrimitive)
In the last case that you say is broken, it falls under the first rule, ("Type(x) is the same as Type(y)" — they are both Object. Then it evaluates the following rule:
Return true if x and y refer to the same object. Otherwise, return false.
String.split
), so the result is false.To illustrate:
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!
The solution, as @nrabinowitz says, is to simply add [0]
to the end of the split call so that the value is the first element (a String) instead of the Array itself.
Upvotes: 1
Reputation: 41832
JavaScript typing is implicit. This means if it thinks you are trying to treat something as a number, it will do it's best to treat that object as a number, even if it is, say, a boolean, or a string.
When doing standard ==
, JavaScript will use implicit conversions to try and match types. This often results in unexpected comparison results.
If you want to force strong comparisons, you must use the ===
operator.
That being said, if you are examining the 'number' representation of a string, e.g. "123", and want to use strong comparisons, you must convert it to a number using parseInt(str, 10);
For some examples on implicit typing in action, see the JavaScript truth table answer.
Upvotes: 7
Reputation: 55678
Here's the problem: ["1"] == 1
in Javascript, because of the implicit conversions @Matt describes. But ["1"] != ["1"]
in Javascript, because you're comparing two arrays, and thus two objects, and object comparisons are only true if they point to the same object, not if they point to two identical objects.
When you assign with .split('/', 1)
, you're getting an array like ['3']
, not the string "3"
(as I think you might be assuming). So:
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"]
To fix this with your current code, you can just get the string, not the array, like this:
currentmonth = currentdate.split("/")[0]; // currentmonth is "3"
opens[i]["date"].split("/")[0] == currentmonth; // true, both sides are "3"
Upvotes: 4
Reputation: 2448
Can you try this just to know if it's a integer vs string failure ?
This is not a nice solution but it gives a clue.
while(opens[i]["date"].split("/", 1) + "str" == currentmonth + "str")
Upvotes: 0