# iSpan 4. JavaScript - 上課筆記本 + 整理
>* HTML
>定義網頁的內容
>* CSS
>定義網頁的外觀(階層樣式表)
>* <font color="crimson">JavaScript
>定義網頁和使用者的互動</font>
w3c的 JavaScript https://www.w3schools.com/js/default.asp
<br><br><br><br>
JS命名規則可以==英文大小寫(區分大小寫)、數字、$和底線==,但禁止首字為數字
## <font color="DodgerBlue">JavaScript</font>
### <font color="mistyrose">使用前先了解 . . .</font>
* Client 和 Server會互傳資料,js 可以在客戶端先處理好部份資訊或運算,**減少Server端負荷**。
-> 客戶端的JavaScript功能要是關閉,若網頁有使用JavaScript的功能將無法運作。
:::success
:book: google瀏覽器的設定 -> 隱私權和安全性 -> 網站設定 -> 下面內容的 JavaScript -> 可以禁止網站使用 JavaScript 。
:::
* 不常更改變動的設定適合使用 Html 撰寫, ==常變動 / 會互動的物件==適合使用 js 撰寫。
* js 在於使用==物件( Object )== ,即==屬性 Proerty==(特徵)和==方法Method==(會動的)的集合
-> 鍵值對 ( key-value ) 的集合,值為基本數據類型為屬性,為函數則為方法。
<br><br>
==HTML DOM 物件==會把HTML檔案轉換成物件,JavaScript就可以對HTML進行變化更改。
>[!IMPORTANT]學習連結:
>* [Browser Object Model](https://www.w3schools.com/js/js_window.asp)
>* [Document Object Model ( The HTML DOM Tree )](https://www.w3schools.com/js/js_htmldom.asp)
1. DOM tree 是 DOM 的樹狀結構。
2. 根節點為 document,代表整份 html 文件。
3. 其他每個節點代表著元素、屬性、文本。
>* [JavaScript and HTML DOM Reference](https://www.w3schools.com/jsref/default.asp)
-> JavaScript / Window / HTML DOM 物件和 Web APIs。
1. **瀏覽器物件模型(Browser Object Model)** 讓 JavaScript 和==瀏覽器對話==以進行操作。
2. **文件物件模型(Document Object Model)** 讓 JavaScript 和==HTML文件對話==以進行操作。
舉 DOM 的一個例子:
  `document.write("水箭龜");`
  則網頁上就會出現水箭龜三個字,甚至還能賦予 html 標籤,例如:
  `document.write("<h1>小火龍</h1>");`
  畫面效果就會長這樣,使用 js 對 html 進行操作更改。

<br><br>
:::success
:book: 三個關於 `<script>` 的補充。
* JavaScript 的使用方式有兩種:
1. 在標籤內直接寫入程式碼。

2. 嵌入外部 JavaScript 檔案。

3. 同時使用。
因為程式碼執行順序,會先執行嵌入的外部檔案,忽略內部文本程式碼且不執行。
* `<script>` 的放置位置妥當,才不會讓使用者覺得網頁讀取時卡頓。
-> ==程式碼執行都是由上至下==
1. 放置在`<head>`區塊內:適合「能夠直接顯示無關運算」的程式碼。
2. 放置在`<body>`區塊尾:適合「需要運算或和 body 內其他元素互動」的程式碼。
* 舊程式碼會看到 `<script type="text/javascript">` 的寫法
-> 舊版需要告訴瀏覽器此段代碼類型為 text/javascript,即 JavaScript 的 MIME 類型。
-> HTML5 後,`<script>` 的 type 默認為 text/javascript。
:::
<br><br>
### <font color="mistyrose">console 主控台</font>
為 BOM 的一個物件。
按下 F12 或是滑鼠右鍵後選擇檢查,主控台就在瀏覽器的開發者工具裡面。
用途為測試、追蹤錯誤、紀錄日記,是工程師開發的重要工具。
* `console.log();` 一般訊息
* `console.error();` 錯誤訊息
* `console.warn();` 警告訊息
* `console.clear();` 清空主控台
* `console.table();` 陣列
* `console.time();` 搭配 `console.timeEnd();` 可以得到包圍程式碼的耗時,比較效能。
* `console.group();` 分組(展開)
* `console.groupCollapsed();` 分組(收合)
* `console.groupEnd();` 表示分組尾端

<br><br>
### <font color="mistyrose">Document 文件</font>
HTML文件在==載入瀏覽器==時,就會變成一份==文件物件==。
文件物件是HTML文件的根結點(root node)。

文件物件也是==window物件的的屬性==。
-> 所以文件物件(document object)==**既是物件也是屬性**==(property)。
-> 使用 `window.document` 或 `document` 皆可。
如果在主控台顯示內容:

* `document.write("...");` 在html內寫上訊息。
* `document.getElementById("...")` 獲取html內指定某id的元素。
:::info
:eyes: document.getElementById("...") 就是需要和 body 內其他元素互動;
若 js 程式碼執行位置在前,則抓取目標就會為 null 。

:::
>[!IMPORTANT]學習連結:
>https://www.w3schools.com/jsref/dom_obj_document.asp
<br><br><br><br>
## <font color="DodgerBlue"> 變數</font>
* 變數==宣告==格式: ==變數類型 變數名;==
->例、變數宣告並賦直 `var x = "小明"; `
* 若未宣告,使用時會跳出錯誤訊息。
* 若未賦值,使用時會跳出關鍵字 undefined。

<br><br>
### <font color="mistyrose">變數命名</font>
命名規則:
1. 僅限英文大小寫 ( 區分大小寫 )、數字、美元符號、底線(A-Z、a-z、0-9、$、_ )。
2. 禁止首字母為數字。
3. 禁止使用保留字 ( reserved word,也叫關鍵字 keyword )。
4. 命名方式一、底線分隔,例: stu_name_id。
5. 命名方式二、大駝峰 Upper Camel Case:StuNameId。
6. 命名方式三、小駝峰 lower Camel Case:stuNameId。
:::success
:book: 害怕使用到保留字,可以在名字前加上my ,例如: myint
:::
>[!IMPORTANT]JavaScript 保留字有哪些:
>https://www.w3schools.com/js/js_reserved.asp
<br><br>
### <font color ="mistyrose">變數類型</font>
1. var,可橫跨block,作用於==函數內==,有==hoisting特性==。
:::success
:book: hoisting特性,JavaScript 編譯階段將變數和函式的宣告存入記憶體的概念,
使函數和變量的==宣告==被==提升==到==作用域的頂部==,即使他們的實際定義位置在下面。
例如下圖兩個程式碼,執行上是相同的。

:::
2. let,block scope ( 區塊作用域 ) 的變數,無法橫跨大括號。
3. const,同let,特點在於==宣告時必須賦值==,之後==無法更改==,適合定義參數如 pi=3.14 等。
:::success
:book: 此處的 block 區塊形容大括號包裹的區域,例如迴圈while(){ ... }
:::
<br><br><br><br>
## <font color ="DodgerBlue">資料型別</font>
使用==typeof==關鍵字取得資料型態類型

<br><br>
### <font color ="mistyrose">String 字串</font>
* **雙引號對或單引號對**包覆即是字串。
* 一些特殊字元需要使用跳脫字元反斜線 `"C:\\temp"` -> `"C:\temp"`。
* 算術運算子**加號**遇到字串會變成字串相接的意思 `"小明"+"好帥"` -> `"小明好帥"`。
* ==Template Literalsa 模板字串==,引號改成==反引號==,使用 ==${ }== 讓文字和變數相接,除此之外還可以直接使用多行字串 (單雙引號多行字串需要用反斜線連接)。


:::success
:book: 常用的跳脫字元 `\'`單引號 `\"`雙引號 `\\`反斜線 `\t`tab `\n`換行
:::
* ==`.length`==
取得字串長度(幾個字元)。
* ==`.indexOf(p)`==
取得第一個特定字串p在字串中的位置,起始位置為0,未找到回傳-1。
* ==`.lastIndexOf(p)`==
取得最後一個特定字串p在字串中的位置,格式上同.indexOf()。
* ==`.split(p1,[p2])`==
根據指定的分隔值p1,將字串切割,回傳一個新字串陣列;p2為保留的切割數量,預設全切。
* ==`.padStart(p1,[p2])`==
把字串的字元數補足到p1個;用p2值取代,預設為空白。
* ==`.substring(p1,[p2])`==
取得字串的其中一部分,回傳為一個新字串。
p1 設定開始位置,p2設定結束位置(==不包含==),預設為字串長度。
編譯時會自動把較小的數字移至p1;負數皆視為0。
* ==`.slice(p1,[p2])`==
同.substring(),但不會編譯時改動p1、p2位置。
負數值 = 字串長度 + 負數值,例、`"abcde.slice(-2) //de"`。
:::success
:book: (p1,[p2])被中括號包起來的參數代表可省略。
:::
<br><br>
### <font color ="mistyrose">Number 數值</font>
1. 正數、負數、小數都是數值。
2. 數值運算常見錯誤:Infinity、-Infinity、NaN (Not a number)。

3. 減乘除(- * /)的運算會==強制把字串轉型成數值==,加號例外。
* ==`Number.MAX_SAFE_INTEGER`==
取得安全處理數字最大值。
* ==`isNaN(p)`==
判斷數值是否為NaN。
* ==`parseInt(p)`==
把字串轉換為數值。
* ==`.toString()`==
把數值轉換為字串。
:::success
:book: Number 能處理的最大範圍 -2^53到2^53之間(不含兩個端點)。
-> 超過範圍的計算就可能出現錯誤。
:::
<br><br>
### <font color ="mistyrose">Array 陣列</font>
1. 陣列使用時機:相同的資料型態(雖然 JavaScript 可以不需要相同,但還是盡量避免)。
2. 具有==一致的意義==、需要參與同樣的運算。
3. 陣列就像置物櫃一樣,透過index,可以存取物品(元素)。
4. 使用==中括號==表示==宣告陣列== 例、`var temp = [10, 20, 30];`。
5. 存放元素進陣列 `temp[3] = [40];`。
6. 從陣列取得元素 `temp[0]`。
7. ==call by reference (傳址)==。
>[!IMPORTANT]傳址和傳值
>1. call by value (傳值):以變數為參照賦予另一個變數值,電腦會在記憶體中新增(複製)一個新值,讓後來的變數指向新的值。
>2. call by reference (傳址):變數會指向電腦記憶體中同樣的物件,不會有新的物件在記憶體中被創造出來,此時兩個變數的更改會互相影響。
>3. 字串和數值為 call by value; 鎮列為 call by reference。
>
>
:::info
:eyes: 列內索引值(index)起始從0開始計算。
:::
:::info
:eyes: JavaScript 的陣列不用先宣告長度,甚至可以跳過前面元素,從後面開始設置。
:::
* ==`.length`==
取得陣列長度(幾個元素)。
* ==`.toString()`==
把陣列轉換為字串。
* ==`.join(p)`==
取得陣列轉換的字串,其中,用參數p替代。
* ==`.shift()`==
移除陣列的第一份資料。
* ==`.pop()`==
移除陣列的最後一份資料。
* ==`.unshift(p)`==
增加資料p到陣列第一個位置。
* ==`.push(p)`==
增加資料p到陣列最後一個位置。
<br><br>
### <font color ="mistyrose">Object 物件</font>
1. 物件使用時機:多個屬性和方法都是形容==同一樣東西==。
2. 物件的屬性,定義物件的特性,例如、人類物件有身高、體重等屬性。
3. 物件的方法,定義物件的行為,例如、人類物件有睡眠、進食等方法。
4. 常見的物件中,有的不會定義方法,但幾乎都會定義==屬性==。
5. 使用大括號表示宣告物件 例、
`var score = {
name:"小明",
math:80,
english:95
}`。
6. 物件的大括號內格式為 `{ key1:value1, key2:value2.. }`。
>物件內為**key-value鍵-值對**,設定key值(屬性名/方法名)後冒號,後面放上value值(屬性值或函數(方法)),多個設定要用逗號分隔。
>JavaScript 會自動把==key值判斷為字串類型==。
7. 使用 . 或 [ ] 可以取得或新增物件內的屬性,例、
更改數學屬性的成績 `score.math = 90;`。
新增科學屬性的成績 `score.science = 1000;`。
更改英文屬性的成績 `score["english"] = 90;`。
新增國文屬性的成績 `score["chinese"] = 1000;`。
<br><br>
### <font color ="mistyrose">Boolean 布林值</font>
1. 只會有兩個值:True 或 False。
2. 常見於比較運算後回傳的結果。
3. 轉換成數值則 True為1 , False 為0。
<br><br>
### <font color ="mistyrose">運算子</font>
* 算數運算子
常見的加減乘除都在此類,此外還有
1. 取餘數% 例、 `10 % 3 = 1` 、 `15 % 4 = 3`。
2. 變數`++`,變數 = 變數 +1 的意思,例、

3. `++`變數,同變數`++`,差異在於若包含在其他式子內,前者會做完式子才+1,後者做之前就+1。

* 比較運算子
評估條件,回傳 true 或者 false 值,常見有>、<、>=、<=。
注意程式和數學常見差異。
1. `==` ,等於,單純比值,無視資料型態,字串"10"和數值10==會==視作相等。
2. `===`,等於,不會自動轉型,字串"10"和數值10==不會==視作相等。
3. `!=`,不等於。
:::info
:eyes: 因為回傳為布林值,建議不要使用連續比較,例、3>2>1 會回傳 False
因為程式由左至右,(3>2)>1執行後變成 (True)>1 -> (1)>1 -> False
:::
* 邏輯運算子
回傳 true 或者 false 值。
1. and (&&) 條件需要同時成立的時候。
2. or (||) 條件擇一成立。
3. 若確定結果程式會直接返回不會繼續判斷,像是 A&&B(A為假) A||B(A為真)。
* 三元運算子
(condition) ? value1:value2,即 (條件|比較) ? 成立執行這段 : 不成立執行這段。
例、`(皮包的錢超過100)? 買一杯手搖 : 回家;`
<br><br><br><br>
## <font color="DodgerBlue">內建函數</font>
### <font color="mistyrose">JavaScrip 內建函數</font>
1. Date 日期物件
生成日期物件,隨參數不同有九種生成方式。

* ==`d.getFullYear()`==
取得年份 ( yyyy ) 。
* ==`d.getMonth()`==
取得月份 ( 0 - 11 ) 。
* ==`d.getDate()`==
取得日期 ( 1 - 31 ) 。
* ==`d.getDay()`==
取得星期 ( 0 - 6 ) 。
* ==`d.getHours()`==
取得小時 ( 0 - 23 ) 。
* ==`d.getMinutes()`==
取得分鐘 ( 0 - 59 ) 。
* ==`d.setdate( p )`==
設置日期 ( 1 - 31) 。
* ==`d.setMonth( p )`==
設置月份 ( 0 - 11 ) 。
:::info
:eyes: 只有日期是從1開始數,所以使用月份要記得+1,星期則是0代表星期日。
:::
:::success
:book: 雖然日期限定填入1-31的數字,但0其實會換算成上個月的最後一天。
:::
:::success
:book: 日期物件相減可以得到時間差,但單位是毫秒。
:::
>[!IMPORTANT]學習連結:
>https://www.w3schools.com/js/js_date_methods.asp
2. Math 數學物件
* ==`Math.random()`==
產生亂數,值為 0~1 ( 不包含1 )。
* ==`Math.ceil(x)`==
數值x無條件進位。
* ==`Math.floor(x)`==
數值x無條件捨去。
* ==`Math.round(x)`==
數值x四捨五入。
>[!IMPORTANT]學習連結:
>https://www.w3schools.com/js/js_math.asp
<br><br>
### <font color="mistyrose"> Window 內建函數</font>
window 在 JavaScript 為全域物件,所以使用屬性和方法==可以省略== window。
> 所以前面 document 章節,才會說 window.document 可以省略為 document。
* ==`window.alert(...);`==
訊息框,內文可以放數值、字串、陣列、變數...等。

* ==`window.confirm(...) `==
確認框,一樣可以放內文,會返回 True / False。

* ==`prompt(...);`==
輸入框,一樣可以放內文,會返回使用者輸入值的==字串==,取消則顯示null。

* ==`setInterval(p1,p2)`==
定義一個==重複計時器==,固定延遲了某段時間之後,才執行對應的程式碼,然後不斷循環。
p1放入函數變數 (無小括號)、函數變數的字串 (有小括號) 或整個函數。
p2放入隔多少毫秒執行一次,注意單位是毫秒。
:::info
:eyes: p1不能直接放入 `Hi()` , 函數的==小括號代表立即執行==。
若放入`Hi()`則立即執行,會導致循環時`Hi()`已執行完畢,內容為空,不會重複執行。
:::
* ==`clearInterval(p);`==
清除使用的 setInterval, p 要放上 setInterval()的變數或函數。
* ==`setTimeout(p1,p2)`==
格式和用法同setInterval,不過只做一次,適合跳轉頁面。
:::success
:book: 使用document.location.href = "..." 更新網址。
:::
* ==`window.getComputedStyle( p1 ).getPropertyValue( p2 )`==
取得指定元素某項樣式的內容 ( 所有樣式來源皆計算 )。
p1 為HTML元素,p2 為樣式屬性。
>[!IMPORTANT]學習連結:
>https://www.w3schools.com/jsref/obj_window.asp
<br><br>
### <font color="mistyrose">DOM 文件物件模型的內建函數</font>
* ==`document.getElementsByTagName("p")`==
取得所有 p 標籤元素。
* ==`document.getElementsByClassName("p")`==
取得擁有 p class 類別的元素。
* ==`document.getElementById("p")`==
取得 id 為 p 的元素。
:::info
:eyes: 前兩個回傳值為HTMLCollection,為類陣列;
而 getElementById 的 element 沒有加 s,回傳為 HTMLElement。
:::
前三個範例:

* ==`HTMLElement.innerText="..."`==
設定內容,只能純文字。
* ==`HTMLElement.innerHTML="..."`==
設定內容,可以包含標籤變化。
* `HTMLElement.屬性`
設定標籤的屬性,例如 img元素設定 src 屬性;
若為非合法屬性則無效果。
* `HTMLElement.style.樣式屬性`
設定元素的==行內樣式==;
若 CSS 屬性為複合字,需要改成小駝峰形式,例如 font-size 成 fontSize。

:::success
:book: 和`window.getComputedStyle( p1 ).getPropertyValue( p2 )`差異在於
一個為行內樣式,一個為最終樣式。
:::
* ==`document.querySelector("#myId")`==
透過 CSS Selectors 取得一個標籤元素。
* ==`document.querySelectorAll(".myGroup")`==
透過 CSS Selectors 取得全部標籤元素,回傳為 ==NodeList==。
:::info
:eyes: 有些方法是針對 ==HTMLElement==,如果取得為 HTMLCollection 或 NodeList ,要指定陣列的哪個元素。
:::
* ==`document.createElement("p")`==
新增p標籤的元素。
* ==`document.createTextNode("...")`==
新增一個文字節點。
* ==`HTMLElement.setAttribute("屬性名稱", "屬性值")`==
對元素設定屬性。
* ==`Node1.appendChild( Node2 );`==
將 Node2 附加到 Node1 上。
* ==`Node1.insertBefore( Node2 , Node3 )`==
在父節點 Node1 下 Node3 節點前插入新節點 Node2。
:::success
:book: Node,為 The HTML DOM Tree of Objects 上面的一個節點;常見的節點有
1. 文檔節點:根節點。
2. 元素節點:HTML 元素。
3. 文本節點:純文本內容。
4. 屬性節點:HTML 元素的屬性。
:::
>[!IMPORTANT]學習連結:
>https://www.w3schools.com/js/js_htmldom_elements.asp
<br><br><br><br>
## <font color="DodgerBlue">流程控制</font>
判斷式內需要為==布林值==。
undefined、null、0、""、NaN 會視為False。
<br><br>
### <font color="mistyrose">if_else判斷</font>
1. 由上而下逐一確認條件,條件符合就進入執行該區域程式。
2. 執行完對應條件的程式後會直接跳出整個if判斷式。

<br><br>
### <font color="mistyrose">switch_case判斷</font>
1. 找尋 case 名稱中和expression一樣的,執行該區域。
2. 會==判斷資料型態==,注意 expr 和 case 的資料型態,例、 "10"和10。
3. 關鍵字`break` 會跳出迴圈。

:::info
:eyes: 若沒有break,則執行完對應區域後會繼續執行下個區域。
所以可以視情況合併條件處理,例如周一到周五上班,周末放假可以寫成如下:

:::
<br><br>
### <font color="mistyrose">while迴圈</font>
1. 當滿足條件時進入迴圈,迴圈結束後會再次確認條件,直至離開迴圈。
2. 離開 while 敘述句的方式:break 或者條件不成立。

<br><br>
### <font color="mistyrose">for迴圈</font>
1. for ==迴圈執行前==執行 statement 1,為宣告變數給初始值。
2. 執行==每次== for 迴圈==前==執行 statement 2,為結束判斷式。
3. 執行==每次== for 迴圈==後==執行 statement 3,為變數累進。

:::success
:book:不同於`break`是跳出迴圈,關鍵字`continue` 是結束當前迴圈,執行下一輪迴圈
:::
<br><br><br><br>
## <font color="DodgerBlue">function 函數</font>

1. 參數可以為空;若要求複數參數,用,隔開。
2. 給予不對應的參數數量或資料類型,可能會有 undefined、意外結果等等。
3. 回傳值可以為空,若有回傳值則限一,且馬上回傳並終止函數,即`return`以下程式==不會執行==。
4. 函數具有 ==hoisting== 的性質,不同於 var 變數,本身的定義內容也會抬升。
<br><br>
### <font color="mistyrose">函數運算式</font>
1. 宣告函數同時宣告一個變數並賦值。
2. 因為馬上賦值變數,不用再給函數做命名。
3. 失去 hoisting 特性(因為此時為 var的 hoisting ,但尚未賦值)。

<br><br>
### <font color="mistyrose">事件屬性</font>
1. button有一個`onclick`屬性,設定後可以和function做連結,代表按下後執行對應函數。

2. 可以在js設定 `HTMLElement.onclick = 函數名稱;`。
3. 或是設定 `HTMLElement.addEventListener('click', 函數名稱);`。
:::success
:book: 這裡函數名稱後面不能加上小括號(),因為是點擊才執行,若加上會立即執行。
:::
>[!IMPORTANT]學習連結:
>https://www.w3schools.com/js/js_functions.asp
>https://www.w3schools.com/js/js_events_examples.asp
>寫在標籤內的事件,例如 onclick。
>https://www.w3schools.com/js/js_htmldom_eventlistener.asp
>事件監聽器 addEventListener,也是==最推薦==的使用方式。
| | HTML屬性 | 事件監聽器 |
| ---------- | ------------------------------ | ---------------------------------- |
| 多個事件 | 限定一個,會被覆蓋 | 可以綁定多個事件 |
| 事件監聽器 | 寫在HTML標籤內,維護性擴展性差 | 和HTML結構分開,邏輯皆在 js 內處理 |
`HTMLElement.onclick = 函數名稱;` 為屬性,所以會覆蓋。
`HTMLElement.addEventListener('click', 函數名稱);` 為函數,不會有覆蓋問題。