由app版本高低判断延伸到javascript字符串比较

最近在参与部门的app 重构,其中有一个是根据后台版本配置与当前 app 版本的表来提示用户是否有新版本,需要更新的提示。然后发现旧的代码直接使用的字符串比较:

1
2
3
const v1 = '1.0.1';
const v2 = '1.0.2';
console.log(v1 > v2); // false

乍一看,好像没问什么问题。但是当出现下面版本时,问题就来了:

1
2
3
const v1 = '1.2.1';
const v2 = '1.12.1';
console.log(v1 > v2); // true

其实这就涉及到了字符串的比较规则,字符串比较是使用基于标准字典的 Unicode 值来进行比较的。

1
2
3
4
5
6
'2' > '1' // true
'abc' > 'acb' // false
// 数字比较
2 > 11 // false
// 字符串比较
'2' > '11' // true

之所以出现 ‘2’ > ‘11’ 为真的情况,字符串比较的情况下会逐个字符进行比较。

1
2
'2'.charCodeAt(0) // 50
'11'.charCodeAt(0) // 49

这样比较,就会出现 ‘2’ > ‘11’ 为 true的情况。

回归到最初的问题,那么 app 版本比较的思路就有了。

补位方法:

既然字符串比较是逐位进行比较的,那么我们就假定主副补丁版本的最高位数为4,不足四位的左侧补齐0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function toNum(version) {
const versionArr = version.split('.');
const num_place = ['0000', '000', '00', '0', ''];
const len = versionArr.length;
for (let i = 0; i < len; i++) {
const itemLen = versionArr[i].length;
versionArr[i] = num_place[itemLen] + versionArr[i];
}
const res = versionArr.join('');
return res;
};

function compareVersion(a, b) {
const version_a = toNum(a);
const version_b = toNum(b);
console.log(version_a);
return version_a > version_b;
}


console.log(compareVersion('1.0.1', '1.1.2')); // false
console.log(compareVersion('0.0.1', '0.0.2')); // false
console.log(compareVersion('1.1.0', '1.2.0')); // false
console.log(compareVersion('1.2.1', '1.12.1')); // false
console.log(compareVersion('1.1.12', '1.2')); // false

数值比较

分别对 主,副,补丁版本的数值进行比较:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function compareVersion(v1, v2) {
const v1arr = v1.split('.');
const v2arr = v2.split('.');
const len1 = v1arr.length;
const len2 = v2arr.length;
const max = len1 > len2 ? len1 : len2;
let i = 0;
for(; i < max; i++) {
const v1v = v1arr[i] ? parseInt(v1arr[i]) : 0;
const v2v = v2arr[i] ? parseInt(v2arr[i]) : 0;
if (v2v > v1v) {
return false;
}
}
if (v1arr.join() === v2arr.join()) {
return false;
}
return true;
}

console.log(compareVersion('1.0.1', '1.1.2')); // false
console.log(compareVersion('0.0.1', '0.0.2')); // false
console.log(compareVersion('1.1.0', '1.2.0')); // false
console.log(compareVersion('1.2.1', '1.12.1')); // false
console.log(compareVersion('1.1.12', '1.2')); // false