當我問表單校驗的面試題時,我期望得到什麼樣的答案

當我問表單校驗的面試題時,我期望得到什麼樣的答案

面試題

校驗用戶名表單,長度為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 正則工具

  • 分析調試工具
    • Regex Buddy, Regex Magic
    • Match Tracer
    • 正則表達式101
    • regex101
    • regexr
  • 可視化分析
    • regulex
    • regexper

推薦閱讀:

Hulu機器學習問題與解答系列 | 二十五:初識生成式對抗網路(GANs)
總結 is 和 == 的區別
軟通動力軟體測試面試題庫
面試時如何回答「你對加班的看法」?

TAG:面試問題 | 正則表達式 |