# 佳萱 Q6-Q10 code review ## Q6 ### validator.js ```javascript! function isEnglish(input) { const A = 65; const Z = 90; const a = 97; const z = 122; const arrayInput = input.split(""); arrayInput.forEach((item) => { const char = item.charCodeAt(0); if (!(A <= char && char <= Z) && !(a <= char && char <= z)) { throw new Error(`請輸入英文字母`); } }); } ``` - `if (!(A <= char && char <= Z) && !(a <= char && char <= z))`建議條件判斷用正向,用更語意化表示,比較好閱讀 - `A <= char && char <= Z` 、`a <= char && char <= z`再命名一個語意化的變數存放 ### Q6module.js ```javascript! export function Q6module(name) { name.forEach((item) => validatorForQ6(item)); const oddNameList = getOddName(name); const oddLettersOfOddName = getOddLetterOfOddName(oddNameList); return oddLettersOfOddName; } ``` Q6module的參數name是傳入一個陣列,如果寫name會看不出來,用`names`或是`nameList`比較知道是什麼型別、是複數的 ```javascript //其他function如參數也是傳入陣列也能比照這方式 function getOddName(name) {...} function getOddLetterOfOddName(name) {...} //修改後 function getOddName(nameList) {...} function getOddLetterOfOddName(nameList) {...} ``` ### getOddLetterOfOddName函式 ```javascript! function getOddLetterOfOddName(name) { const oddLetter = nameList .map((item) => item.split("")) .map((item) => item.filter((_, index) => index % 2 === 0)); const [firstName, thirdName] = oddLetter; return `${name[0]}的奇數字母為${firstName}\n${name[1]}的奇數字母為${thirdName}`; } //修改後 function getOddLetterOfOddName(nameList) { const oddLetter = nameList.map((item) => item.split("").filter((_, index) => index % 2 === 0) ); const [firstName, thirdName] = oddLetter; const firstNameLetter = nameList[0]; const thirdNameLetter = nameList[1]; return `${firstNameLetter}的奇數字母為${firstName}\n${thirdNameLetter}的奇數字母為${thirdName}`; } ``` - `name[0]`和`name[1]`直接閱讀不知道代表什麼意思,可再命**變數**較好閱讀,例如:`const firstNameLetter = nameList[0];` - 寫題目通常就先符合題目,再更進階的話,考慮到擴充、變化是否可更適用需求,例如:6個名字時候 ### main.js ```javascript! function main() { const names = []; initial(names) .then((name) => askQuestion("請輸入第1個英文名字:", name)) .then((name) => askQuestion("請輸入第2個英文名字:", name)) .then((name) => askQuestion("請輸入第3個英文名字:", name)) .then((name) => askQuestion("請輸入第4個英文名字:", name)) .then((name) => Q6module(name)) .then((name) => console.log(name)); } ``` - then後面的參數name建議改為names,跟一開始傳入一致 ## Q7 ### Q7module.js - getEmptyArray函式建立空陣列可放在rotate90Degree函式裡面 ## Q8 ### Q8module.js ```javascript! function divi(n, count = 1) { const divisor = 3; // const times = count; let number = n / divisor; const secondDecimalPoint = Math.floor(number * 100) % 10; if (secondDecimalPoint === 0) { return count; } else { return divi(number, count + 1); } } ``` - count部份較不直覺,我設定count參數預設值1,他自己會另外命變數存放,例如:`const times = count`,看個人做法 ## Q9 ### Q9module.js - 兩個陣列相加,forEach方式外,map方式也嘗試 ```javascript! const rl = readline.createInterface看起來每題都有,可以組成模組引入使用 ``` ## 其他 - JS17專注邏輯,試著完整邏輯自己先想過,1天解不出來就問 - 看完題目寫步驟,把每一步驟->組成程式,試著將邏輯自己寫完,再看別人的程式碼優化 - JS30他們那屆有跳過一些題目,寫題目也沒有按照順序,主要練習到web api操作 - 佳萱自己先在工作室接案,才開始有接api的經驗,後來再去找工作 - vscode有live share套件,選擇share(read/write)對方直接修改程式碼可以同步看到,遠端code review很方便 ![image](https://hackmd.io/_uploads/SJ-A3OeiC.png) # 嬿媜 Q6-Q10 code review ## Q6 ```javascript! function getOddLetterOfOddName(oddNameList) { const oddLetterList = oddNameList.map((item) => item.split("").filter((_, index) => index % 2 === 0) ); const [firstNameLetter, thirdNameLetter] = oddLetterList; const firstOddName = oddNameList[0]; const thirdOddName = oddNameList[1]; return `${firstOddName}的奇數字母為${firstOddNameLetter}\n${thirdOddName}的奇數字母為${thirdOddNameLetter}`; } //建議修改 const [firstOddNameLetter, secondOddNameLetter] = oddLetterList; const firstOddName = oddNameList[0]; const secondOddName = oddNameList[1]; return `${firstOddName}的奇數字母為${firstOddNameLetter}\n${secondOddName}的奇數字母為${secondOddNameLetter}`; } ``` 在看的時候,會不懂為什麼是firstNameLetter和thirdNameLetter,建議寫firstOddNameLetter和secondOddNameLetter ## Q8 ```javascript! //嬿媜覺得此寫法是單一次使用,如要複用寫閉包方式會較適合 function divi(n, count = 1) { const divisor = 3; let number = n / divisor; const secondDecimalPoint = Math.floor(number * 100) % 10; if (secondDecimalPoint === 0) { return count; } else { return divi(number, count + 1); } } //改成閉包寫法 function divi(n) { let number = n; let count = 0; const divisor = 3; function inner() { number = number / divisor; count++; const secondDecimalPoint = Math.floor(number * 100) % 10; if (secondDecimalPoint === 0) { return count; } else { inner(); } } inner(); } divi(5); ``` ## Q10 ```javascript! function main() { const array = [3, 50, 0, 13, 2, 4, 11]; const elementAndIndex = array.map((integer, index) => ({ integer, index })); //箭頭函式return物件加上小括號() console.log(elementAndIndex); const primeNumber = elementAndIndex.filter((item) => getPrimeNumber(item.integer) ); primeNumber.forEach((item) => console.log(`${item.integer}是質數, 索引值為${item.index}`) ); } main(); //原map裡面的item,index改成integer,index,才不會都是item無法辨認 ``` # Chris Q6-Q10 code review ## Q6 ```javascript! function initial(answer) { return new Promise((resolve) => resolve(answer)); } function main() { const names = []; initial(names) .then((names) => askQuestion("請輸入第1個英文名字:", names)) .then((names) => askQuestion("請輸入第2個英文名字:", names)) .then((names) => askQuestion("請輸入第3個英文名字:", names)) .then((names) => askQuestion("請輸入第4個英文名字:", names)) .then((names) => Q6module(names)) .then((names) => console.log(names)); } main(); ``` - .then裡面的`(names) => askQuestion("請輸入第1個英文名字:", names)`都是先註冊而已,全部.then註冊完**才開始看條件是否成立**,條件成立才開始丟到queue佇列,也就是當輸入完按下Enter時,下一個問題就會到queue排隊 - 非同步:條件成立才執行 - names其實都一直重複,pure寫法是柯里化 ```javascript! //柯里化 function main() { const names = []; initial(names) .then(askQuestion(`請輸入第一個英文名字:`)) //askQuestion其實是return function .then(askQuestion(`請輸入第二個英文名字:`)) .then(askQuestion(`請輸入第三個英文名字:`)) .then(askQuestion(`請輸入第四個英文名字:`)) .then(Q6module) .then(console.log); } main(); function askQuestion(question) { return (answer) => { return new Promise((resolve) => { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.question(question, (strInput) => { try { rl.close(); //問問題後馬上關掉 validatorForQ6(strInput); resolve([...answer, strInput]); } catch (error) { console.log(error.message); resolve(askQuestion(question)(answer)); } }); }); }; } ``` ### Q6module.js `filter((_,index)=>index % 2 === 0)`我有兩個地方使用到,Chris認為這是一件事,可以做成一個function odd(取奇數) ```javascript! function odd(_, index) { return index % 2 === 0; } ``` ```javascript! //原本寫法 function getOddName(nameList) { //item沒有使用到用底線表示 const oddName = nameList.filter(filter((_,index)=>index % 2 === 0)); return oddName; } //修改後 function getOddName(nameList) { //item沒有使用到用底線表示 const oddName = nameList.filter(filter(odd); return oddName; } ``` ```javascript! //以下命名Chris會傾向用first和third開頭 function getOddLetterOfOddName(oddNameList) { const oddLetterList = oddNameList.map((item) => item.split("").filter(odd)); const [firstOddNameLetter, secondOddNameLetter] = oddLetterList; const firstOddName = oddNameList[0]; const secondOddName = oddNameList[1]; return `${firstOddName}的奇數字母為${firstOddNameLetter}\n${secondOddName}的奇數字母為${secondOddNameLetter}`; } ``` ### validator.js ```javascript! //Chris修改 export function isLetters(input) { const A = 65; const Z = 90; const a = 97; const z = 122; const arrayInput = input.split(""); arrayInput.forEach((item) => { const char = item.charCodeAt(0); const uppercaseAlphabetRange = A <= char && char <= Z; const lowercaseAlphabetRange = a <= char && char <= z; // if (!(A <= char && char <= Z) && !lowercaseAlphabetRange) { if ((char < A || Z < char) && !lowercaseAlphabetRange) { throw new Error(`請輸入英文字母`); } }); } ``` - function名isEnglis改成isLetters - 原本學長姐建議把判斷再用變數存放 ```javascript! const uppercaseAlphabetRange = A <= char && char <= Z const lowercaseAlphabetRange = a <= char && char <= z; ``` Chris認為會比較難懂,他會使用笛摩根定律來修改有反向的判斷 ```javascript! //原本 if (!(A <= char && char <= Z) && !(a <= char && char <= z){} //修改 if ((char < A || Z < char) && (char < a || z < char)){} ``` Chris說isBinOctHexAndE這個命名太好笑,直接寫不是十進位isDecimal更直覺 ```javascript! //原本 export function isBinOctHexAndE(input) {} //修改後 export function isNotDecimal(input) {} ``` vscode -> help -> editor playground可以查詢一些快捷方法,例如某函式的命名要修改,此函式在很多隻檔案使用,就可以用F2修改分散在各地的函式名字 ![image](https://hackmd.io/_uploads/r1oF2OejR.png) ### test.js 測試的標題和toThrow報錯括號內要寫清楚 ```javascript! //原本 test(`未輸入`, () => { const input = ["", "", "", ""]; const act = () => Q6module(input); expect(act).toThrow(); }); //修改 test(`未輸入,會出現請輸入內容`, () => { const input = ["", "", "", ""]; const act = () => Q6module(input); expect(act).toThrow("請輸入內容"); }); ``` ## Q7 - 函式命名修改:原本getStringToArray,把get拿掉用to就可以代表動作 - 先filter再map可以少跑,減少效能 ```javascript! function stringToArray(string) { return string .split("\n") .filter((item) => item.length !== 0) //因為愛心字串第一行為空,把空的篩選掉 .map((item) => item.split("")); } ``` - 建立空陣列 function getEmptyArray 如果是走訪,才需要用null 如果是賦值,直接放**空陣列、空物件**就可以 ```javascript! //原本 function getEmptyArray(array) { return Array(array[0].length) .fill(null) .map(() => Array(array.length).fill(null)); } //修改 function getEmptyArray(array) { //建立9個位置,用null是因為直接放空陣列,是屬於共用同一個空陣列 //map直接放空陣列是因為每一個都是獨立的,不會共用 return Array(array[0].length) .fill(null) .map(() => []); } ```