面試題
校驗用戶名表單,長度為8-10位的只包含數字和字母的字符串,用JavaScript實現一個校驗函數。
1 解決過程
1.1 首先確認題目需求(幾乎沒有人確認過,當然也沒有人寫對過)
1.1.1 題目要求
長度8-10位
只包含數字和字母
JS校驗函數
1.1.2 Tips
幾乎沒人確認過
沒人寫對過
如果這里有問題,后面肯定對不了
1.2 其次分析思路(轉換為可以寫代碼的等價邏輯表達,也沒人寫對過)
1.2.1 等價邏輯轉換一
包含字母
包含數字
只能是數字和字母
-
長度8-10位
?
1.2.2 等價邏輯轉換二
不 全為數字
不 全為字母
只能是數字和字母
長度8-10位
1.2.3 等價邏輯轉換三
所有字符ASCII碼在數字和字母的范圍內
長度8-10位
1.2.4 Tips
即使前面需求理解清楚,這里轉換不等價也得不到正確的結果
有了這里面的等價分解,最基本的TestCase也就有了,便于后面做校驗
即使寫不出代碼來,這里能說清楚也行
說不清楚也行,需要能看到不斷嘗試,積極思考的過程
1.3 然后是核心代碼實現(清一色的正則,我們也先說正則)
1.3.1 使用零寬正向先行斷言
1.3.1.1 代碼實現
/^(?=.*\d.*)(?=.*[a-zA-Z].*)[0-9a-zA-Z]{8,10}$/.test(str)
1.3.1.2 代碼解釋
(?=)
表達正向先行斷言,滿足條件的其他匹配結果才為真,即括號內的表達式匹配整個匹配結果才為真可以出現在代碼的任意位置
不占用最終的匹配寬度
這里表達既包含數字又包含字母的只包含數字和字母的8-10位的字符串
1.3.1.3 邏輯表達
包含數字
包含字母
8-10位的數字和字母的組合(全匹配)
1.3.2 使用零寬負向先行斷言
1.3.2.1 代碼實現
/^(?!\d+$)(?![a-zA-Z]+$)[0-9a-zA-Z]{8,10}$/.test(str)
1.3.2.2 代碼解釋
(?!)
表達負向先行斷言,滿足非條件的其他匹配結果才為真,即括號內的表達式不匹配整個匹配結果才為真可以出現在代碼的任意位置
不占用最終的匹配寬度
這里表達不全為數字且不全為字母的只包含數字和字母的8-10位的字符串
1.3.2.3 邏輯表達
不全為數字的(全匹配)
不全為字母的(全匹配)
8-10位的數字和字母的組合(全匹配)
1.3.2.4
1.3.3 如果不知道上面的方式,可以拆分一下
1.3.3.1 代碼實現
!/^\d+$/.test(str) && !/^[a-zA-Z]+$/.test(str) && /^[0-9a-zA-Z]{8,10}$/.test(str)
1.3.3.2 代碼解釋
- 不解釋了,直接的邏輯表達
1.3.3.3 邏輯表達
不全為數字的(全匹配)
不全為字母的(全匹配)
8-10位的數字和字母的組合(全匹配)
1.3.4 如果不知道正則怎么玩,也可以用字符判斷的方式
1.3.4.1 代碼實現
//考慮記不住ASCII碼
var rangeChars = '09azAZ';
var char0Code = rangeChars.charCodeAt(0),
char9Code = rangeChars.charCodeAt(1),
charaCode = rangeChars.charCodeAt(2),
charzCode = rangeChars.charCodeAt(3),
charACode = rangeChars.charCodeAt(4),
charZCode = rangeChars.charCodeAt(5);
Array.from(str).every(char => {
return '0' <= char && char <= '9' || 'a' <= char && char <= 'z' || 'A' <= char && char <= 'Z'
});
Array.from(str).some(char => {
return '0' <= char && char <= '9'
});
Array.from(str).some(char => {
return 'a' <= char && char <= 'z' || 'A' <= char && char <= 'Z'
});
8 <= str.length && str.length <= 10
1.4 最后是結果的輸出
export const validationUtil = {
isNameValid:(str) => {
//調用isNameValid 的同時,不應該有判斷undefind,判斷null的過程,表單取出來的不會有這倆值
str += '';
str = str.trim();
return /^(?!\d+$)(?![a-zA-Z]+$)[0-9a-zA-Z]{8,10}$/.test(str);
}
}
2 常見問題
校驗不寫trim
正則不寫首尾匹配
/^[0-9a-zA-Z]{8,10}$/ 作為題目結果
自己寫出來的正則,自己也不知道啥意思
3 參考資料
3.1 正則書籍
-
基礎
學習正則表達式
正則表達式必知必會
神奇的匹配
-
進階
精通正則表達式
正則指引
3.2 正則工具
-
分析調試工具
-
可視化分析