出來混總是要還的-JS正則前傳

ntscshen發表於2018-10-17

前言: 正規表示式一直是個人痛點, 相信很多人 ( 說的就是你 ) 跟我一樣存在類似的情況, 正則是反覆學, 反覆忘, 從個人角度看主要的原因還是:較少的使用場景, 如果像陣列的幾個常用方法一樣, 絕大多數人肯定能熟練運用。 最近迫使我拿起正則這把屠龍刀的起因是( 時間充足和一道小的面試題 ), 那我們們就先從這道面試題說起

Demo1

// 觀察如下規律, 寫一個函式`accum`
// accum("abcd");      // "A-Bb-Ccc-Dddd"
// accum("helloWorld");   // "H-Ee-Lll-Llll-Ooooo-Wwwwww-Ooooooo-Rrrrrrrr-Lllllllll-Dddddddddd"
// accum("China");      // "C-Hh-Iii-Nnnn-Aaaaa"
複製程式碼

看到題的第一反應就是, 握草這還不簡單, 兩層迴圈加上珍藏多年的字串拼接技術(-_-||), 妥妥的解決這個問題

const accum = str => {
  let result = "";
  str.toLowerCase().split("").forEach((el, idx) => {
      for (let i = 0; i <= idx; i++) {
        if (i == 0) {
          result += el.toUpperCase();
        } else {
          result += el;
        }
      }
      result += el + "-";
    });
  return result.slice(0, -1);
  // 看到slice慌不慌?是不是忘記這鬼東西是幹什麼的了?和substr/string有什麼區別?
};
console.log(accum("CHina"));
複製程式碼

寫完並且測試結果正確, 就開始沾沾自喜, 感覺萬事大吉。( 這種狀態很像在工作中, 寫完功能不去優化一樣 )

上面的一坨程式碼, 對, 就是一坨程式碼, 一坨像極了業務功能的邏輯程式碼, 沒有精巧的思路, 沒有精緻的寫法。 這踏馬跟鹹魚有什麼區別?

優雅的迴圈

const accum = str => {
  let result = "";
  for (let i = 0; i < str.length; i++) {
    const temp = str[i];
    result += temp.toUpperCase();
    for (let j = i; j > 0; j--) {
      result += temp.toLowerCase();
    }
    result += "-";
  }
  return result.slice(0, -1);
};
console.log(accum("CHina"));
複製程式碼

優雅的迴圈, 優雅的迴圈, 優雅的迴圈 啊、啊、啊!

精緻的利己主義者

const accum = str => {
  return Array.from(str.toLowerCase(), (item, index) => {
    return (
      item.toUpperCase() + Array.from({length: index}, () => {
          return item;
        }
      ).join("")
    );
  }).join("-");
};
console.log(accum("CHina"));
複製程式碼

放蕩不羈的 reduce

const accum = str => {
  return Array.from(str.toLowerCase()).reduce((accu, cur, idx) => {
      accu.push(cur.toUpperCase().padEnd(idx + 1, cur));
      return accu;
    }, []).join("-");
};
console.log(accum("CHina"));
複製程式碼

百辟匕首( RegExp )

匹配與獲取字串方法

const accum = str => {
  return str.toLowerCase().replace(/\w{1}/gi, (item, idx) => {
      let temp = "";
      Array.from(new Array(idx)).map(() => {
        temp += item;
      });
      return `${item.toUpperCase()}${temp}-`;
    }).slice(0, -1);
};
console.log(accum("CHina"));
複製程式碼

怎麼樣, 最後幾種方案看的是不是很刺激、很驚喜, 其實就是一堆奇葩操作, 這是 API 操作者的狂歡, 也是 JS 開發者的基本功^_^

這幾個方案裡面最令人驚喜的還是 replace, 當第二個引數是一個函式, 當第一個引數為正規表示式並且為全域性匹配模式時, 這個方法每次匹配都會被呼叫。

replace 應該是正則的 6 個常用 API 中最強大的一個, 它可以拿到你想要的資訊, 並且假借替換之名, 做一些神奇操作

傳送門 -> JS正則常用的有四種操作: 驗證、切分、提取、替換

注:

  1. \w 匹配單詞字元, 等價於[0-9a-ZA-Z_], 數字字母下劃線
  2. {1} 連續出現 1 次

夯實基礎

相關文章