# 比较版本号
版本号规范: {major}.{minor}.{patch}-{alpha | beta | rc}.{number}
版本号示例:1.3.2 1.3.2-alpha 1.3.2-rc.1
1.3.2 < 1.3.3
1.3.2-alpha < 1.3.2-beta < 1.3.2-rc
1.3.2-rc < 1.3.2-rc.1 < 1.3.2
v1 > v2 返回 1
v1 = v2 返回 0
v1 < v2 返回 -1
const VERSION_REGEXP = /(\d{1,})\.(\d{1,})\.(\d{1,})-?(alpha|beta|rc)?\.?(\d{1,})?/;
const PreRelease = {
alpha: 1,
beta: 2,
rc: 3
};
// 比较函数
const compare = (v1, v2, isPre) => {
if (!v1 && v2) {
return isPre ? -1 : 1;
} else if (v1 && !v2) {
return isPre ? 1 : -1;
}
if (v1 > v2) {
return 1;
} else if (v1 < v2) {
return -1;
}
return 0;
};
const compareVersion = (v1, v2) => {
if (v1 === v2) {
return 0;
}
// 通过正则解析提取 major minor path 等信息
const v1Match = v1.match(VERSION_REGEXP);
const v2Match = v2.match(VERSION_REGEXP);
// 使用最长的数组元素遍历
const len = Math.max(v1Match.length, v2Match.length);
for (let i = 1; i < len; i++) {
// 对索引为 4 的 alpha beta rc 做特殊处理
// 同时对先行版本号的 number 进行特殊判断
const result = i === 4 ? compare(PreRelease[v1Match[i]], PreRelease[v2Match[i]]) : compare(v1Match[i], v2Match[i], i > 4);
// 当 判断结果不为 0 时直接返回
if (result !== 0) {
return result;
}
}
return 0;
};
console.log('0', compareVersion('1.3.2', '1.3.2'));
console.log('-1', compareVersion('1.0.0', '1.3.2'));
console.log('1', compareVersion('2.0.0', '1.3.2'));
console.log('-1', compareVersion('1.3.2', '1.3.3'));
console.log('1', compareVersion('1.3.2', '1.3.2-alpha'));
console.log('-1', compareVersion('1.3.2-alpha', '1.3.2-beta'));
console.log('-1', compareVersion('1.3.2-beta', '1.3.2-rc'));
console.log('-1', compareVersion('1.3.2-rc', '1.3.2-rc.1'));
console.log('-1', compareVersion('1.3.2-rc.1', '1.3.2'));