最近在参与部门的app 重构,其中有一个是根据后台版本配置与当前 app 版本的表来提示用户是否有新版本,需要更新的提示。然后发现旧的代码直接使用的字符串比较:
1 2 3
| const v1 = '1.0.1'; const v2 = '1.0.2'; console.log(v1 > v2);
|
乍一看,好像没问什么问题。但是当出现下面版本时,问题就来了:
1 2 3
| const v1 = '1.2.1'; const v2 = '1.12.1'; console.log(v1 > v2);
|
其实这就涉及到了字符串的比较规则,字符串比较是使用基于标准字典的 Unicode 值来进行比较的。
1 2 3 4 5 6
| '2' > '1' 'abc' > 'acb'
2 > 11
'2' > '11'
|
之所以出现 ‘2’ > ‘11’ 为真的情况,字符串比较的情况下会逐个字符进行比较。
1 2
| '2'.charCodeAt(0) '11'.charCodeAt(0)
|
这样比较,就会出现 ‘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')); console.log(compareVersion('0.0.1', '0.0.2')); console.log(compareVersion('1.1.0', '1.2.0')); console.log(compareVersion('1.2.1', '1.12.1')); console.log(compareVersion('1.1.12', '1.2'));
|
数值比较
分别对 主,副,补丁版本的数值进行比较:
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')); console.log(compareVersion('0.0.1', '0.0.2')); console.log(compareVersion('1.1.0', '1.2.0')); console.log(compareVersion('1.2.1', '1.12.1')); console.log(compareVersion('1.1.12', '1.2'));
|