# JS (Day3)
filter範例 (找出大於3的數字)
```javascript=
const list = [1, 2, 3, 4, 5];
let result = list.filter(function (a) {
return a > 3;
});
console.log(result);
```
filter收集結果,map收集並產生陣列
## reduce
reduce(function(累加值,目前))
將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列歸納成單一值。
fn每輪的return會變成下一輪的累加值(acc)
acc若沒給初始值會將陣列中第一個元素當初始值,並少執行一圈
範例(沒給初始值)
```javascript=
const list = [1, 2, 3, 4, 5];
let a = list.reduce(function (acc, cv) {
return acc + cv;
};
console.log(a);
```

範例(給初始值)
```javascript=
const list = [1, 2, 3, 4, 5];
let a = list.reduce(function (acc, cv) {
console.log(acc, cv);
return acc + cv;
}, 10); //acc的初始值
console.log(a);
```

範例(找出最大的數)
* fn每輪的return會變成下一輪的累加值(acc)
```javascript=
const list = [19, 23, 3, 2, 24];
let a = list.reduce(function (acc, cv) {
//第一輪 acc → 19
//第一輪 cv → 23
console.log("acc=", acc, "cv=", cv);
if (cv > acc) {
return cv;
} else {
return acc;
}
});
console.log(a);
```

---
## Object 物件
物件 = 屬性(properties) + 行為(method)
```javascript=
let cat = {
age: 2,
name: "meow",
attack: function () {
console.log("gogo!!");
},
};
console.log(cat.age);
console.log(cat.name);
console.log(cat);
cat.attack();
```

加屬性
```javascript=
let cat = {
age: 2,
name: "meow",
attack: function () {
console.log("gogo!!");
},
};
cat.color = "red"; //新增color屬性到Cat物件中
```
delete 去除屬性
```javascript=
let cat = {
age: 2,
name: "meow",
attack: function () {
console.log("gogo!!");
},
};
delete cat.age; //刪除cat物件中age的屬性
```
---
## DOM (Document Object Model)
將頁面透過瀏覽器物件化,用JS來抓取並控制這些物件
### getElementById
getElementById
<div id="cc" class="xx">123</div>
```javascript=
const c = document.getElementById("cc");
console.log(c);
```

### getElementsByClassName
抓取所有class一樣的物件
<ul id="list">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
</ul>
```javascript=
const c = document.getElementsByClassName("item");
console.log(c);
```

### querySelector
```htmlembedded=
<div id="cc" class="xx">123</div>
```
```javascript=
const c = document.querySelector("#cc");
console.log(c);
```
可以運用CSS選取器
範例(抓取第三個li):
<ul id="list">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
</ul>
```javascript=
const b = document.querySelector("#list :last-child");
console.log(b);
```
### querySelectorAll
```javascript=
const c = document.querySelectorAll(".item");
console.log(c);
```

:::warning
HTMLCollection和NodeList都不是陣列,但NodeList比HTMLCollection多一個forEach可以運用

:::
練習
將原本的內容印出五倍長
<ul id="list">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
</ul>
```javascript=
const items = document.querySelectorAll(".item");
items.forEach(function (item) {
item.textContent = item.textContent.repeat(5);
});
console.log(items);
```
---
### textContent vs innerHTML
前者是單純字串,後者是可以加入標籤或是添加屬性
```javascript=
const item = document.querySelector("#test");
item.innerHTML = "<h1>444</h1>";
```
### JS 添加屬性方式
```javascript=
item.style.color = "red";
```
```javascript=
item.style["color"] = "red";
```
### 抓取CSS宣告的屬性,直接新增到HTML tag中
add 增加class
remove 移除class
<h1 id="test" class="xx">123</h1>
```css=
.hi {
color: white;
background-color: red;
}
```
```javascript=
const item = document.querySelector("#test");
item.classList.add("hi"); //改remove就是移除hi
```
綜合練習(讓奇數的li 套用hi)
<ul id="list">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
<li class="item">4</li>
<li class="item">5</li>
</ul>
```css=
.hi {
color: white;
background-color: red;
}
```
```javascript=
const items = document.querySelectorAll(".item");
items.forEach(function (item, idx) {
if (idx % 2 === 0) {
item.classList.add("hi");
}
});
```
---
## Event 事件
1. JS事件發生在瀏覽器的事件(resize the screen, scroll, click)
2. JS Event發生時,需要event listener了解JS Event的細節.
### addEventListener
先選擇在監聽
addEventListener(event type, callback)
event type: resize the screen, scroll, click...
callback function : parameter
同一個物件可以加N個監聽器
#### click event
```javascript=
document.addEventListener("click", function () {
console.log("點了");
});
```
#### 將事件添加到物件中
(點擊123的時候觸發click event)
<h1 id="test" class="text123">123</h1>
```javascript=
const c = document.querySelector(".text123");
c.addEventListener("click", function () {
console.log("點了");
});
```
將function另外寫,當成值丟進去
```javascript=
const h = document.querySelector(".text123");
const text = function () {
console.log("HIHI123");
};
h.addEventListener("click", text);
```
### 設置讀取完介面再執行JS方法
1. 若JS文件讀取不是在下方,同時又不能更改HTML文件內容時,可設置此指令再JS外圍,用意為先讓DOM的內容讀取完再執行JS。
```javascript=
document.addEventListener("DOMContentLoaded", function () { JS程式 })
```
2. 在後面加上defer做延遲
```javascript=
<script src="./app.js" defer></script>
```
## 高階函數(式) Higher-Order Function
1. 接別的函數當參數/引數
2. 可以回傳一個函數
---
## 防止預設行為
防止物件預設行為,像是右鍵選單,超連結跳轉,表單送出
```javascript=
const btn = document.querySelector(".btn");
btn.addEventListener("click", function (e) {
e.preventDefault();
console.log("hi");
});
```
---
#### SRP = Single Resposibility Principle
---
Event 練習
練習一:簡易計數器(不能小於0)
```
<button id="minus">-</button>
<input type="number" id="counter" value="1">
<button id="plus">+</button>
```
```javascript=
document.addEventListener("DOMContentLoaded", function () {
const plus = document.querySelector("#plus")
const minus = document.querySelector("#minus")
const num = document.querySelector("#counter")
plus.addEventListener("click", () => {
num.value++
})
minus.addEventListener("click", () => {
if (num.value > 0) {
num.value--
}
})
})
```
練習二(計算BMI)

```javascript=
document.addEventListener("DOMContentLoaded", function () {
const h = document.querySelector("#bodyHeight")
const w = document.querySelector("#bodyWeight")
const result = document.querySelector("#resultText")
const btn = document.querySelector("button")
btn.addEventListener("click", function () {
let height = h.value / 100
let weight = w.value
let BMI = Number(weight) / (Number(height) * Number(height))
result.textContent = String(BMI.toFixed(2))
})
})
```