---
# System prepended metadata

title: JS(8/10) Day 25 五倍紅寶石(第八屆共筆)(2021/7/30)
tags: [JavaScript]

---

# JS(8/10) Day 25 五倍紅寶石(第八屆共筆)(2021/7/30)
## password 練習:
### 常用的方法：
- .split(""):可以將字串打散，讓裡面的每個字元變成陣列的值。
ex:"abc123".split("") => ["a","b","c",1,2,3]
- .toUpperCase():英文字轉成大寫。
- .toLowerCase():英文字轉成小寫。
ex:"Abc".toLowerCase() 可以用來判斷原字串有沒有大寫的英文字。
- +:字串轉成數字。
ex:+"aaa" => NaN
   +"1"   => 1
- isNaN():會將()的內容物轉型成數字，並判斷是不是NaN。
ex:isNaN(1) => false
   isNaN("a") => true
  !isNaN(1) => true (1是數字)

- .find():()內接一個函式，可以找到有沒有符合條件的東西，有的話回傳那個值回來，只會傳第一個滿足條件的值。
ex:[1, 2, 3, 4, 5].find((x) => x < 5)  =>  回傳 1
- .some():()內接一個函式，可以找到有沒有符合條件的東西，有的話回傳布林值回來，只要其中有一個符合就可以。
ex:[1, 2, 3, 4, 5].some((x) => x < 5)  =>  回傳 true
- .trim():可以去掉字串內的空白字元。
實務上可以先用此方法去掉空白字元再檢查密碼輸入的情形符不符合我們的規則，主要是防止使用者亂打一堆空白。

## Functional Programming:(FP)
拆解大問題至各個小問題，每個小問題都用一個 Function 寫出來，
好處是可以獨立使用且方便做測試。
心法:能寫函式就寫函式，不要一直宣告變數用for迴圈或是if else。

## Regex:(正規表達式)
用來搜尋特定字元。
可參考 [mdn](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Regular_Expressions)
[測試網站](https://regex101.com/) [測試網站(Ruby)](https://rubular.com/)

## Error Handling:(例外處理)
Exception:例外，在執行過程中發生錯誤。
可以抓到像(ReferenceError、TypeError...等錯誤)，但抓不到 SyntaxError，因為語法錯誤程式連執行都沒辦法執行。
- try:當 try 執行的程式碼發生錯誤時，不會被中斷，會跳到 catch 裡面執行 catch 的程式碼。
- catch:可帶入參數、或是使用console.error()讓 catch 印出錯誤訊息。
```js=
catch(err) {
  console.log(err)
}
```
- finally:不管成功或失敗都一定會做。(選擇性寫)
- throw new:用來替換原本的錯誤訊息，當上面的 if 條件式成立的時候，就會執行這段，執行完後會立刻將控制權轉交到 catch。
Error 是錯誤訊息的名字，可自行修改。
後面()跟 console.log 一樣會直接印出。
```js=
if (result !== expected) {
  throw new Error(`${result} 與預期的 ${expected} 不符!`)
}
```
```js=
// 用VSCode測試才準，不要用 JSBIN
const moreThanChars = (chars, n) => /.{8,}/.test(chars)

test("應該要超過 8 個字 part 1", () => {
  let result = moreThanChars("abc", 8)
  expect(result).toBe(false)
})

test("應該要超過 8 個字 part 2", () => {
  let result = moreThanChars("abc283209138021832", 8)
  expect(result).toBe(true)
})

function test(title, callback) {
  try {
    callback()
    console.log(`✓ ${title}`);
  } 
  catch(err) {
    console.error(`✗ ${title}`)
    console.error(err)
  }
}

function expect(result) {
  // return 物件
  return {
    // toBe是物件裡面的屬性，值為箭頭函式
    toBe: (expected) => {
      if (result !== expected) {
        throw new Error(`${result} 與預期的 ${expected} 不符!`)
      }
    }
  }
}
```
## What is `this`?
window 跟 global 是全域物件，var a = 1 的 a 會變成全域物件。
=> 會在 window 上面插旗: window.a = 1。
在甚麼都沒有的狀況下寫 console.log(this)，this 會指向 window，會印出 window 物件可以使用的方法。

### this 的六條規則：
0. 有沒有用 new
1. 是否使用「嚴格模式」
2. 誰呼叫，誰就是 this
3. 前面沒有人，this -> global、window
4. 是否有使用 bind / call / apply
5. 使用箭頭函數 () => { } ，箭頭函數沒有自己的 this / arguments

### 綁定 this 的三種方法:
#### bind vs call vs apply
- 共同點：
  原本的 this 是指向全域物件 window ，使用 bind、call、apply 可以將 this 指向帶入的第一個引數，而第二個引數開始則為一般我們認知上的引數。
- Function.prototype.bind():
  - **必須將他指派為一個物件(函式)**。
  - **會建立一個新的函式**。
  - 引數可帶入多個。
```=js
const Olympics = {
  event: "羽球",
  player: "小戴"
}

function play(result, review) {
  console.log(`${this.event}比賽結果: ${this.player}${result}，${review}`)
}
// 寫法1:把引數寫在 bind 後面
const badmintonResult = play.bind(Olympics, "贏了", "好棒")
badmintonResult()
// 印出：羽球比賽結果: 小戴贏了，好棒

// 寫法2:把引數寫在已宣告的物件上
const badmintonResult = play.bind(Olympics)
badmintonResult("贏了", "好棒")
// 印出：羽球比賽結果: 小戴贏了，好棒
```
- Function.prototype.call():
  - 可以直接呼叫，不用將他指派為物件。
  - 不會產生新的函式。
  - **引數可帶入多個**。
```=js
const Olympics = {
  event: "羽球",
  player: "小戴"
}

function play(result, review) {
  console.log(`${this.event}比賽結果: ${this.player}${result}，${review}`)
}

play.call(Olympics, "贏了", "好棒")
// 印出：羽球比賽結果: 小戴贏了，好棒
```

- Function.prototype.apply():
  - 可以直接呼叫，不用將他指派為物件。
  - 不會產生新的函式。
  - 引數只能帶入**一組陣列**。
```=js
const Olympics = {
  event: "羽球",
  player: "小戴"
}
  
function play(result, review) {
  console.log(`${this.event}比賽結果: ${this.player}${result}，${review}`)
}
  
play.apply(Olympics, ["贏了", "好棒"])
// 印出：羽球比賽結果: 小戴贏了，好棒
```

arguments 不會印出 undefined。
箭頭函式沒有自己的 arguments，也沒有自己的 this，所以也不能使用 new 來建立箭頭函式。

在 SayMyName 函式裡跟 setTimeout 函式裡的 this 不一樣，外面的 this 因為呼叫的人是 hero 所以指向 hero，裡面的 this 沒人呼叫，指向 window，所以想把 hero 綁進去要用 .bind。
```=js
const hero = {
  name: "物空",
  sayMyName: function() {
    setTimeout(
      function() {
        console.log(this.name)
      }.bind(this), 100
    )
  }
}
hero.sayMyName()
```

## 嚴格模式:
因為 JS 本身太鬆散，所以後來才添加這個模式讓他能用這個方式增加嚴謹度，變得跟正常的程式語言一樣。
用法為"use strict"，寫在整份文件最上方或是函式最上方。
名稱為字串是因為這是後來才出現的語法，為了讓老舊的機器看不懂也不會出錯才使用字串。

## TDD(Test-Driven Development):
用程式來測試(驗證)程式對不對，看有沒有跟預期一樣，萬一程式碼被修改，可以測試出來哪裡被更動。
寫測試建議抽出來用 function 寫，會比較好懂，寫測試不求短，求清楚好懂。
專注在怎麼測才對就好，框架可用別人的。(可參考facebook/jest)
- 測試 3A:
1. Arrange:把東西準備好
2. Act:踹一踹
3. Assertion(斷言):測試式子

## Module
### 各大套件&名詞解析:
npm(Node Package Manager)
cdn(類似一個雲端空間)
purgeCSS:purge = 清除，可以幫你把沒有用到的 CSS 拿掉，讓效能變好
parsel.js:打包工具

npm init:跟 git 一樣每個目錄都要先 init 才能做事，按 enter 全部確定。
npm i bootstrap:安裝 bootstrap 在本地端，不用去 cdn 抓回來。
json 最後一個 key 的值不能加,不然會出錯。
如果玩壞可以把nod-modules刪掉再用 npm -i 裝回來。

---

[JS Xmind](https://www.xmind.net/m/jbs5GK)

---

###### tags: `JavaScript`
