# 佳萱 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很方便

# 嬿媜 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修改分散在各地的函式名字

### 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(() => []);
}
```