views:

344

answers:

6

Looking in the jQuery core I found the folloiwng code convention:

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

And I was really curious about the snippet match[3] - 0

Hunting around for '-0' on google isn't too productive, and a search for 'minus zero' brings back a reference to a Bob Dylan song.

So, can anyone tell me. Is this some sort of performance trick, or is there a reason for doing this rather than a parseInt or parseFloat?

Thanks

+9  A: 

Probably just a short-hand way to force the left-hand side into integer. Not as clear as calling a function, of course.

This tutorial on type-conversion states:

Any mathematical operator except the concatenation/addition operator will force type-conversion. So conversion of a string to a number might entail performing a mathematical operation on the string representation of the number that would not affect the resulting number, such as subtracting zero or multiplying by one.

This also reveals that "subtracting" is a better search term than "minus". :)

unwind
Thanks for the link
James Wiseman
+2  A: 

Your main reason to use this syntax is if you have generic code that may be any number (int or float) and you want to do a type-sensitive compare (===)

Sohnee
A: 

If it's not an old relic that got lost, then it just tries to change the type to Number.

elias
I realise it changes a type to a number. I was hoping for explanation as to why it was done this way.
James Wiseman
A: 

It really looks like a "performant" parseInt to me.

Kind Regards

--Andy

jAndy
+8  A: 

Based on a few quick and dirty benchmark runs, "1234" - 0 was about 50% faster than parseInt("1234") and 10% faster than +"1234" in Firefox 3.6.

Update:

My "quick and dirty" benchmark was not very useful because it was just converting the string "1234" in a loop. I tried again using a random list of numbers, and the results are all over the map. The three methods are all within 400-500 ms on this computer except when they jump to 1300 ms! I think garbage collection is interfering. Here is some code to play with in Firebug, in case I did something stupid:

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);
James M.
Why is that so?
Rosdi
I'm not familiar with the implementation, but I would guess there is overhead with calling the `parseInt` function (and it has somewhat different behavior). Since `+` is also used for string concatenation, determining its context may be a source of overhead in that case. No idea if performance was the reason for using -0, but it's an interesting coincidence.
James M.
Thanks for taking the trouble to do this. I wonder if there is any comparitive difference between +0 and -0, as highlighted in @S.Mark's post.
James Wiseman
+0 will append 0 to the string instead of converting it to a number. Also, I wrote a new test that has some different results and will update the answer shortly.
James M.
btw, the unary + I've mentioned in my answer supposed to be `+"1234"` not `"1234" + 0`
S.Mark
+4  A: 

Just a info, According to this site

using unary + operator is faster one than any of the following (which include '- 0'):

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

unary + operator also type-converts its operand to a number and because it does not do any additional mathematical operations it is the fastest method for type-converting a string into a number.

This contradicts James' benchmark, although he may be might be correct. I think jQuery wouldn't utilise this syntax if it were slow.

S.Mark
+1 for being a wise unicorn...
Reigel
+1. "slow" is a relative term. James's benchmark, whilst a good "quick and dirty" example, is based on Firefox only. Different JavaScript implementations differ in their performance optimizations and the same may not be true of other browsers (only one way to find out really).
Andy E