本次的實作專案為短網址產生器,使用者只要輸入 URL,就能獲得獨一無二的短網址。每一組 URL 都只會對應到一組短網址,因此就算重新輸入 URL,也將得到一樣的結果。
短網址從以下元素當中,隨機抽出 5 個元素組合而成:
我們直覺會想到先把這些元素都塞進一個陣列裡面,寫出隨機產生短網址的函式。但這就遇到了一個沒那麼棘手,卻使人心煩的問題:
怎麼辦?好不想手動把這些元素打到陣列裡面喔 😑
既然都要寫函式隨機產生短網址了,有沒有可能也用函式自動包含英文字母 + 整數 0 ~ 9 的陣列啊?
經過一番探詢後,最終還真的成功寫出來了,如果正在看這篇文章的你也有類似的怠惰,歡迎參考以下做法喔。
// 寫一個函式:產生大寫字母 + 小寫字母 + 數字的 collection
function generateCollection() {
const digits = [...Array(10)].map((_, i) => i);
const lowerCaseLetters = [...Array(26)].map((_, i) =>
String.fromCharCode(i + 97)
);
const upperCaseLetters = [...Array(26)].map((_, i) =>
String.fromCharCode(i + 65)
);
return digits.concat(lowerCaseLetters, upperCaseLetters);
}
首先,我們先透過 Array()
建構子產生一組陣列,裡面帶入 26 這個參數,代表我們希望這個陣列有 26 個項目的空間。用 console 列印出來,會顯示 [empty x 26]
。
Array(26);
// return [empty x 26]
接著透過 destructor 將這些空位丟到陣列裡面,到這步,陣列裡面都還是 undefined
:
[...Array(26)]
// return [undefined, undefined, undefined...]
接下來,我們希望陣列中 26 個空位,能塞入 0 ~ 25 的整數,這邊可以善用 array.map()
的方法,裡面需要帶入一個 callback 函式,陣列中每個項目會被 map 一一抓出來,經過 callback 函式處理,然後回傳一個新陣列。
callback 函式裡面,其實還可以叫出 index 這個參數,我們就是要透過 index,把 0 ~ 25 塞入到陣列裡面。
至於 callback 函示的第一個參數 element,由於目前都是 undefined
,而且我們也用不到它們,所以簡單加個下底線意思一下就好。
[...Array(26)].map((_, i) => i);
// returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
接下來就是高潮了,我們取得 0 ~ 25 其實是為了使用 String.fromCharCode()
,將數字轉換成 UTF-16 code units。
[...Array(26)].map((_, i) => String.fromCharCode(i));
// returns ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\b', '\t', '\n', '\v', '\f', '\r', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19']
當然像是 \x00
、\x01
和羅馬字母仍是天差地別,所以後續我們要來參考 w3school 提供的對照表,以羅馬字母的部分,和大家熟悉的 ASCII 編號是一樣的。
對照之後,可以發現小寫字母序號為 97 ~ 122,大寫字母則是 65 ~ 90。太棒了,馬上把這個模式應用到程式碼裡面。
[...Array(26)].map((_, i) => String.fromCharCode(i + 97));
// returns ["a", "b", "c", "d"...]
大寫字母和小寫字母的處理方式基本一樣,最後透過 array.concat()
把三個不同的陣列合併起來就好囉。
// 寫一個函式:產生大寫字母 + 小寫字母 + 數字的 collection
function generateCollection() {
const digits = [...Array(10)].map((_, i) => i);
const lowerCaseLetters = [...Array(26)].map((_, i) =>
String.fromCharCode(i + 97)
);
const upperCaseLetters = [...Array(26)].map((_, i) =>
String.fromCharCode(i + 65)
);
return digits.concat(lowerCaseLetters, upperCaseLetters);
}