---
# System prepended metadata

title: JavaScript 基礎課程 (7)
tags: [JavaScript]

---

---
robots: noindex, nofollow
tags: JavaScript
---

# JavaScript 基礎課程 (7)

## 上次上課提要
- Loop（迴圈）
  - While Loop
    符合某條件時，重複執行某件事
    ```javascript=
    let randomNumber = 0;

    while (randomNumber < 0.5) {
      randomNumber = Math.random();
      console.log(randomNumber);
    }
    ```
  - For Loop
    重複執行某件事固定的次數
    ```javascript=
    for (let i = 0; i < 5; i++) {
      console.log(i);
    }
    ```
    搭配陣列使用
    ```javascript=
    //    index    0  1  2  3  4
    let numbers = [1, 2, 3, 4, 5];

    for (let i = 0; i < numbers.length; i++) {
      console.log(numbers[i]);
    }

    for (let number of numbers) {
      console.log(number);
    }

    numbers.forEach(function printNumber(number) {
      console.log(number);
    });
    // for each number in numbers, print each number
    ```
  - `break`：跳脫迴圈
  - `continue`：跳過某一次迭代

## 網頁的 JavaScript 是怎麼執行的？
  - 我們打開瀏覽器
  - 輸入網址連到某個網站
  - 那個網址的伺服器會回傳一份 HTML 文件 `index.html`
  - 瀏覽器收到文件後，一行一行閱讀（它看得懂 HTML、CSS、JavaScript）
  - 只要瀏覽器發現 HTML 裡面有 JavaScript，就會執行

## 如何在網頁裡放入 JavaScript？
  ```html=
  <html>
    <head>
      <!-- Inline Script -->
      <script>
        console.log('Hello');
        console.log('World');
      </script>

      <!-- External Script -->
      <script src="scripts.js"></script>
    </head>

    <body>
    </body>
  </html>
  ```

> 講到這邊會發現，之前幾堂課教的 JavaScript 大部分都跟網頁互動沒什麼關係，比較像是教你怎麼儲存跟轉換資料⋯⋯

## JavaScript 怎麼知道現在 HTML 長怎樣的？
倚靠一個叫做 Document Object Model (DOM) 的東西。它是對應 HTML 結構的 JavaScript 物件，也是 HTML 跟 JavaScript 的橋樑。我們可以利用它來存取、甚至改變 HTML Document。

![DOM Tree](https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work/dom.gif)

> 有興趣的同學可以參考下列文件（預告：就算切換到中文還是很不好懂）：
> https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model
> https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction

## JavaScript 套路
- 操縱 HTML
  先選到某個 HTML 元素，再操縱它（例如：讀取／改變它的值、複製它、刪除它）。
- 監聽事件
  觀察視窗或使用者的狀態，當某些行為／事件發生時，觸發特定的動作。

## 操縱 HTML
**先選**到某個元素，之**後**再改**變**它。

### 選取元素
```html=
<html>
  <head>...</head>

  <body>
    <header>
      <nav>...</nav>
    </header>

    <div>
      <h1>...</h1> <!-- 假設目標要選到它 -->
      <div>
        <p>...</p>
        <p>...</p>
        <p>...</p>
      </div>
    </div>

    <footer>...</footer>
  </body>
</html>
```

#### 抽絲剝繭、層層推進
```javascript=
document.body // <body>
document.body.children // [<header>, <div>, <footer>]
document.body.children[1] // <div>
document.body.children[1].children // [<h1>, <div>]
document.body.children[1].children[0] // <h1>

document.body.children[1].children[1].children[2] // 最後一個 <p>
```

#### Document.querySelector()
- Input: CSS 選擇器
- Output: 選到的**第一個**元素 或 `null`

```javascript=
// 有符合 CSS 選擇器的元素
let h1Tag = document.querySelector('h1');
console.log(h1Tag); // <h1>
 
// 沒有符合 CSS 選擇器的元素
let h2Tag = document.querySelector('h2');
console.log(h2Tag); // null
```

---

#### 資料型別：`null`
刻意表示沒有值的資料型別。`null` 跟 `undefined` 很容易搞混，前者是「有值但沒內容」，後者是「還沒有值」。

---

#### Document.querySelectorAll()
- Input: CSS 選擇器
- Output: 包含選到所有元素的陣列 或 空陣列 `[]`

```javascript=
// 有符合 CSS 選擇器的元素
let divTags = document.querySelectorAll('div');
console.log(divTags); // [<div>, <div>, ...]
 
// 沒有符合 CSS 選擇器的元素
let hrTags = document.querySelectorAll('hr');
console.log(hrTags); // []
```

### 改變元素

#### 移除元素
```javascript=
let emptySpan = document.querySelector('spanaqio');
if (emptySpan !== null) {
  emptySpan.remove();
}
```

#### 變更元素的屬性或樣式
```javascript=
// 改變某個 <p> 的文字
let pTag = document.querySelector('p');
pTag.textContent = '新的文字';

// 改變某個 <div> 的樣式
let divTag = document.querySelector('.hello'); // <div>

// 增減 class
divTag.classList.add('hidden'); // <div class="hidden">
divTag.classList.remove('hideen'); // <div>

// 加上 inline styles
divTag.style.color = 'gray'; // <div style="color: gray;">
divTag.style.display = 'none'; // <div style="color: gray; display: none;">
```

#### 新增元素
```javascript=
// 產生一個 <div>
let myDiv = document.createElement('div');

// 改變 <div> 的文字
myDiv.textContent = '平凡無奇的 DIV';

// 把 <div> 加到 <body> 裡面
let bodyTag = document.querySelector('body');
bodyTag.appendChild(myDiv);
```

## 程式練習
1. 更新 `.eslintrc.json`：
```json=
{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "airbnb-base"
  ],
  "parserOptions": {
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "rules": {
    "func-names": "off",
    "linebreak-style": "off",
    "no-alert": "off",
    "no-console": "off",
    "no-continue": "off",
    "no-param-reassign": [
      2,
      { "props": false }
    ],
    "no-plusplus": [
      "error",
      { "allowForLoopAfterthoughts": true }
    ],
    "no-restricted-syntax": [
      "error",
      {
        "selector": "ForInStatement",
        "message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array."
      },
      {
        "selector": "LabeledStatement",
        "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
      },
      {
        "selector": "WithStatement",
        "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
      }
    ],
    "prefer-arrow-callback": "off",
    "prefer-const": "off",
    "prefer-template": "off"
  }
}
```
4. 下載 `where-are-the-cats.zip`
5. 解壓縮到 `javascript-basics` 底下的 `src` 資料夾裡
6. 打開 `javascript-basics/src/where-are-the-cats/scripts/code-challenge.js`
7. 按照裡面說明寫出對應的程式碼
8. 想辦法讓網頁看起來變成[這樣](https://mingjunlu.github.io/lazy-loading-example/)

## w13 作業
:::danger
期限：**5/23（週日）23:59**
:::

### 1. 完成上述程式練習
- 完成上述程式練習後，單獨將 `where-are-the-cats` 資料夾上傳到 Netlify 後，繳交網站連結到 [monday.com](https://gsstw.monday.com/boards/1074623203/)

### 2. 透過 Slack 發問
- 可問：
  - 上課的內容
  - 跟 JavaScript 有關的問題
  - 看不懂的 ESLint 錯誤訊息
  - 寫作業或課堂練習時遇到的困難
- 程式類的問題請附上程式碼或錯誤訊息
  - 行數少的話，直接用 Slack 的 code block 功能附上
  - 行數多的話請貼到 CodePen 再附上連結
- 跟別人問一樣的問題也沒關係，總之習慣發問就對了


---


<div style="display: flex; justify-content: space-between;">
  <a href="https://hackmd.io/@gsscsid/javascript-basics-6">⬅️&nbsp;JavaScript 基礎入門課程 (6)</a>
  <a href="https://hackmd.io/@gsscsid/javascript-basics-8">JavaScript 基礎入門課程 (8)&nbsp;➡️</a>
</div>
