I am wondering why the following works:
oldversion = "1.3.52";
newversion = "1.3.54";
if (newversion > oldversion) {
console.log('test');
}
but this does not:
if (1.3.54 > 1.3.52) {
console.log('test');
}
I know that the last example won't work because they are not actual numbers. But I am trying to find out what JavaScript is doing when it encounters a string with a number in it.
This is what I found on W3Schools' JavaScript Comparison and Logical Operators page:
When paring a string with a number, JavaScript will convert the string to a number when doing the parison.
So how e it converts the string to a number and suddenly I am not getting an Uncaught SyntaxError: Unexpected number
anymore?
I am wondering why the following works:
oldversion = "1.3.52";
newversion = "1.3.54";
if (newversion > oldversion) {
console.log('test');
}
but this does not:
if (1.3.54 > 1.3.52) {
console.log('test');
}
I know that the last example won't work because they are not actual numbers. But I am trying to find out what JavaScript is doing when it encounters a string with a number in it.
This is what I found on W3Schools' JavaScript Comparison and Logical Operators page:
When paring a string with a number, JavaScript will convert the string to a number when doing the parison.
So how e it converts the string to a number and suddenly I am not getting an Uncaught SyntaxError: Unexpected number
anymore?
-
1
1.3.54
this is not a number, simple as that.1
is a number or1.3
is a number but adding further dots is invalid. – VLAZ Commented Oct 6, 2016 at 12:09 - 1 It's just doing a string pare.. So using this for version checking would be wrong. – Keith Commented Oct 6, 2016 at 12:10
-
1
"It works" for the strings you have tested. Try
1.23.5
vs1.3.5
… – deceze ♦ Commented Oct 6, 2016 at 12:14 - 1 Last time I checked 12 was greater than 3 :) – Keith Commented Oct 6, 2016 at 12:26
- 1 @Keith OP is getting confused about lexicographic parison the same way Javascript is… :D – deceze ♦ Commented Oct 6, 2016 at 12:27
4 Answers
Reset to default 4You could use a function which iterates the segments.
function checkVersion(a, b) {
var aa = a.split('.').map(Number),
bb = b.split('.').map(Number),
i,
r = 0,
l = Math.max(aa.length, bb.length);
for (i = 0; !r && i < l; i++) {
r = (aa[i] || 0) - (bb[i] || 0);
}
return r;
}
var oldversion = "1.3.52",
newversion = "1.3.54";
if (checkVersion(newversion, oldversion) > 0) {
console.log('test');
}
As mentioned in the ments, it's actually doing a string pare and not trying to turn anything into numbers.
You can verify this by trying:
var a = "a";
var b = "b";
console.log(a>b) // gives false
var a = "a";
var b = "b";
console.log(b>a) // gives true
As you say, when you pare a number and a string, the string gets transformed into a number. However, if the string contains an invalid number, the result will be NaN. This is funny due to the fact that:
NaN > 15 === false
NaN < 15 === false
So:
"1.3.52" > 1.4 === false
"1.3.52" < 1.4 === false
Obviously (and as you said in your post), paring 1.3.52 with 1.3.54 will throw an exception because they're not valid numbers.
Why "1.3.52" is interpreted bigger than '1.12.10'?
Strings are pared using Unicode code point order. For example, "Banana" es before "cherry". "9" is bigger than "80", but because "80" es before "9" in Unicode order. Thus, "1.3.52" is interpreted as bigger than '1.12.10'.
An easy way to find out order between strings and not getting tricked is using sort. For instance, ["1.3.52", "1.12.10", "1.11.0.0.0"].sort()
@Nina's solution should be the accepted answer, as it will be easier to understand I think. But anyway..
function versionGreaterEqual(newversion, oldversion) {
var ov = oldversion.split('.').map(Number), //credit Nina :)
nv = newversion.split('.').map(Number);
return nv.reduce(function (a,b,i){
return a+=b>=ov[i];
},0)===nv.length;
}
console.log(versionGreaterEqual("1.3.54", "1.3.52")); //true
console.log(versionGreaterEqual("1.3.54", "1.13.52")); //false