在用微信绊率、支付寶掃碼支付時,會彈出一個數(shù)字鍵盤(帶有小數(shù)點)究履。在輸入金額時滤否,會對用戶輸入的金額進行糾正,比如輸入 .1 會自動變?yōu)?0.1最仑,輸入 03 會變?yōu)?3藐俺。
那么我們如何實現(xiàn)這樣一個功能呢?
需求分析
考慮到數(shù)字鍵盤泥彤,用戶只能輸入 0-9 和小數(shù)點欲芹。
我們要實現(xiàn)的是一個函數(shù),把用戶輸入的字符串轉化為合法金額的字符串全景。經(jīng)過分析有如下情況:
- 空字符串:輸入 ''耀石,返回 '';
- 以 0 開頭的字符串:輸入 '03'爸黄,返回 '3'滞伟;
- 以 . 開頭的字符串:輸入 '.',返回 '0.'炕贵;
- 3 位小數(shù):輸入 '0.258'梆奈,返回 '0.25';
- 兩個小數(shù)點:輸入 '0.98.'称开,返回 '0.98'亩钟;
- 合法輸入:輸入 '3.',返回 '3.'鳖轰;
如何實現(xiàn)
根據(jù)以上分析清酥,編寫一下驗證腳本:
function normalizeCurrency(input) {
// 具體功能實現(xiàn),最終返回字符串
}
// 驗證腳本
const cases = [
{ input: '', output: '' },
{ input: '03', output: '3' },
{ input: '.', output: '0.' },
{ input: '0.258', output: '0.25' },
{ input: '0.98.', output: '0.98' },
{ input: '3.', output: '3.' }
];
cases.forEach((c, index) => {
if (normalizeCurrency(c.input) === c.output) {
console.log(`case ${index} pass`);
} else {
throw `case ${index} fail: expect ${c.output} but ${normalizeCurrency(c.input)}`;
}
});
簡單的條件判斷實現(xiàn)
function normalizeCurrency(input) {
// 為空的情況
if (input === '') {
return '';
}
const pointIndex = input.indexOf('.');
if (pointIndex > -1) {
// 保留兩位小數(shù)
input = input.slice(0, pointIndex + 3);
// 去掉末尾多余小數(shù)點
if (input.lastIndexOf('.') !== pointIndex) {
input = input.slice(-1);
}
// 首位小數(shù)點前補 0
if (pointIndex === 0) {
input = '0' + input;
}
} else {
// 去掉多余的 0
input = Number(input) + '';
}
return input;
}
比較容易想到這種方法蕴侣,針對分析的每種情況都特殊處理焰轻,但是看起來有點繁瑣,有沒有更好的辦法呢昆雀?
利用 split 方法
function normalizeCurrency(input) {
if (input === '') return '';
const parts = input.split('.');
const integer = Number(parts[0]);
const point = parts[1] !== undefined ? '.' : '';
const decimal = (parts[1] || '').slice(0, 2);
return integer + point + decimal;
}
該方法利用了 split 的一些特性辱志,代碼看起來要簡潔一些了蝠筑,還有沒有更簡潔的實現(xiàn)了?
正則表達式實現(xiàn)
function normalizeCurrency(input) {
if (input === '') return '';
return input.replace(/(\d*)(\.\d{0,2})?.*/, (match, p1, p2) => {
return Number(p1) + (p2 || '');
});
}
通過正則表達式揩懒,代碼變得最為簡潔什乙,也更容易理解一些。