---
# System prepended metadata

title: F_Q6-Q10 code review
tags: [CodeReview]

---

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