## Introduction
:::info
- Javascript能改變html的內容
- `getElementById()`是用來查找特定id名稱的html元素,並改變該元素內容
```html
<p id="demo">JavaScript能夠改變HTML內容</p>
<button type="button" onclick='document.getElementById("demo").innerHTML = "Hello JavaScript!"'>點擊我</button>
```
點擊前

點擊後

- p.s. JavaScript同時接受單引號和雙引號
- 可通過`display`樣式隱藏元素
```html
<p id="demo">JavaScript能夠隱藏HTML元素</p>
<button type="button" onclick="document.getElementById('demo').style.display='none'">
點擊我!
</button>
```
點擊前

點擊後

- `display="block"`顯示隱藏的block
:::
## Javascript v.s. Typescript
:::success
- Typescript
- Javascript的超集 → 任何有效的 JavaScript 程式碼也是 Typescript 的有效程式碼,但增加一些javascript沒有的功能 eg.Interfaces、Generics、Enums
- 主要用途:允許開發者在程式碼中添加類型註解,並提供靜態類型檢查,也就是在編譯時能檢測出許多常見錯誤(變數類型錯誤、方法不存在等),從而增加程式碼的可靠性、可讀性和可維護性
- 優點:提高程式碼的可讀性、和Js相容、利於寫大型專案(因為它提供了模組化和名稱空間的支持,有助於保持代碼的結構性和可擴展性)
:::
:::info
- Javascript和Typescript差別
| | Javascript | Typescript |
| -------- | ---------- | ---------- |
| 類型系統 | Javascript 是動態型別的語言,意味著變數的類型可以在程式執行期間改變(type的檢查在執行時才做)。 | Typescript 則是靜態型別語言,變數的類型在宣告時就已確定,這有助於在程式碼執行之前找出可能的錯誤。 |
| 編譯器 | Javascript無需編譯即可在瀏覽器中直接執行。 | Typescript 需要編譯才能變成 Javascript 程式碼才能在瀏覽器中執行。 |
| 物件導向程式設計 | Javascript 雖然也有 class 與 object,但並無 interface,相對於 Typescript 而言物件導向程式設計的表達較不直覺。 | Typescript 支援 interface、class 和 object,可以更直觀地進行物件導向程式設計。
:::
## 基本語法
:::success
### 在HTML中加入JavaScript
- 法一:
- 將JavaScript程式碼放入`<script>...</script>`標籤,鑲嵌在`<body>`或`<head>`中任意位置
- `<body>` → 頁面加載時被執行,速度增加
- `<head>` → 在被調用的时候才執行、會傳入參數的function
- 法二:
- javascript code寫成獨立的檔案(.js),引用外部.js檔案(可以引用多個) `<script src="URL/檔案路徑/檔案名稱"></script>`
- 通常外部引用放在`<head>`最前面
:::
## Output
:::info
- `innerHTML`可改變HTML內容('='後面可以接變數、數字、文字、算式…)
```
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = 5 + 6;
</script>
```
- `document` → 目前的HTML文檔
- `innerHTML` → 定義HTML要顯示/替換的內容
- `id` → 定義的HTML元素
- `document.write()` - 改變HTML內容(通常用於測試)
- 限制:不能在頁面加載完成(所有的內容都顯示於瀏覽器上)以後使用,會覆蓋整個頁面內容
- eg:
(加載完成後使用`document.write()`)
```
<p>My first paragraph.</p>
<button type="button" onclick="document.write(5 + 6)">Try it</button>
```

頁面加載完成
**↓**

再按button會覆蓋整個頁面
(加載過程中使用`document.write()`)
```html
<p>My first paragraph.</p>`
<script>
document.write(5 + 6);
</script>
```

3. `alert()` - 以下拉視窗顯示內容
```html
<script>
alert(5+6);
</script>
```

- `console.log()` - debug時在控制台顯示某個數值顯
- 括弧內可以放入一個或是多個參數或變數,可印出布林值、變數值、字串等
- 按F12可以debug→選擇”console” → 再次執行就會看到內容
:::
## Statement
:::success
- javascript由多個Statement(一行指令)組成,每段程式結尾都是以分號表示,但JavaScript能夠自動幫你在未加上分號的結尾加上分號(不加容易出錯!)
### Keyword
(後面會介紹)

:::
## Syntax
:::info
- 可以用 "" 或 '’
- ‘+’可以連接兩個字串 eg:`"John" + " " + "Doe”` → John Doe
- 大小寫不同 eg:LET != let
- 命名方式
1. Hyphens連字號
eg:first-name
2. Underscore
eg:first_name
3. Upper Camel Case (Pascal Case)
eg:FirstName
4. Lower Camel Case
eg:firstName
:::
## Comment
:::success
- 單行://
- 多行:/* */
:::
## Javascript 變數
::: info
- JavaScript 變數可以透過 4 種方式宣告:
- Automatically:未宣告變數型別,系統自動宣告成var
- var:可用於全域、區域變數,若重複宣告會覆蓋先前的值,如果全域與區域中有同名的變數,則區域會暫時覆蓋全域
- let:用於宣告只作用於當前區塊的變數
- var定義了一個全域變數,或是在整個function而不管該區塊範圍;let變數範圍是在其定義的區塊內(只存活在{}內)
- var或let變數若未賦值則被定義為undefinded,無法存取
```
function varTest() {
var x = 1;
{
var x = 2; // 這裡的 x 與 function 區塊內部的 x 是一樣的,因此會影響 function 區塊內所有的 x
console.log(x); // 2
}
console.log(x); // 2
}
```
```
function letTest() {
let x = 1;
{
let x = 2; // 這裡的 x 與 function 區塊內部的 x 是不同的,只會作用在這層block區塊中
console.log(x); // 2
}
console.log(x); // 1
}
```
- const:用於宣告只作用於當前區塊的變數,為唯獨變數,不可修改
| | 作用範圍 | redeclare | reassign | this指向當前對象 |
| ----- | -------- | ------------------- | -------- | --- |
| var | 全域 | O(以第二次的值為主) | O |O |
| let | 區域 | X | O | X |
| const | 區域 | X | X | X |
:::
## Operation
:::success
### Arithmetic Operators

- ** → 指數,Math.pow(x,y)相等於`x = x ** y`或`x **= y`
### Comparison Operators
比較運算元的型別和值

- == 和 !=:假如兩個運算元不具有相同型別,在比較時會嘗試轉換成相同型別
- === 和 !==:不轉換成相同型別,嚴格進行比較
- 數字+數字為數字和,字串+數字為字串
- ternary operator:`條件 ? 值1 : 值2`若條件為true則回傳值1,反之回傳值2
### Type Operators

- typeof:回傳代表運算元類型的字串 eg.function、string、number、object
### Bitwise Operators
- 運算元(十進制)被轉換為 32 bits 的整數以二進位形式表示 ,大於 32 bits 的數字將被捨棄多出來的位元
- 運算子會對於 bit 進行運算,結果也是基於 bit 來決定的

- 移動運算子會將運算元轉換成 32 bits 的整數,並且會回傳與左方運算元相同的型態
###
:::
## DataType
:::success
8種Datatypes
- String
- Number
- Bigint
- Boolean
- Undefined
- Null
- Symbol
- Object-{name:value,name:value}
- object
- array
- date
:::
## Function
:::info
- 組成:有特定功能的block of code
- 語法:
1. declaration(JS會自動將宣告提升到現在scope的最頂端,所以可以在宣告前先呼叫)
```
function function_name(參數){
...
}
```
2. expression(function內容可以存入變數)
```
const 變數 = function (參數){//return內容};//因為被視為一行執行程式所以要加分號
```
eg:
```
const x = function (a, b) {return a * b};
let z = x(4, 3);//x變成function代稱可以用來呼叫function
```
3. function() constructor
```
const 變數 = new Function(參數和return算式);
```
4. arrow function
```
const 變數 = (參數) => {要return 的值}
```
- 沒有this → 不能用在object method
- 不能被自動提升成全域 → 要在使用前宣告
- 通常用const因為回傳值是常數
- Parameter → 列在括號內的變數名
argument → 呼叫時傳入的值
回傳型態為function → 因為JavaScript為動態型別
- Argument:pass by value
Object:pass by reference
- 呼叫:
1. Function名:取得funtion的內容
2. Function名():計算function取得結果
3. function constructor:用new呼叫function(建立一個物件,因為function算是一個物件)
eg:
```
// This is a function constructor:
function myFunction(arg1, arg2) {
this.firstName = arg1;
this.lastName = arg2;
}
// This creates a new object
const myObj = new myFunction("John", "Doe");
// This will return "John"
myObj.firstName;
```
:::
## Object
:::success
- 變數的一種,可以包含許多值,一對值寫為`name : value`
eg.`const objectName = {name1:value1, name2:value2, name3:value3};`
### Object Properties
- 屬性是與object關聯的值,object是無序屬性的集合,通常可以更改、新增和刪除
- 存取屬性
1. objectName.propertyName
2. objectName[“propertyName”]
- 新增屬性
- existObject.newPropertie = "newValue";
- 刪除屬性(包含值)
- delete existObject.existPropertie
### Object method
- this
- https://blog.techbridge.cc/2019/02/23/javascript-this/
- 代表一個object,不是代表一個變數,所以不能改變this的值
- 代表哪個object取決於如何被呼叫

- 無論嚴格或非嚴格模式下,this在函數外皆代表全域變數;在函數內則取決於該函是如何被呼叫
- 嚴格模式下,this值預設為undefined
- 可以用call、apply、bind改變this的值
- call():用傳入的參數覆蓋this的值
- apply():和call相同,差別為傳入的參數須為array
- bind():會回傳一個新function,將該function綁定傳入的參數值
- Accessing Object Methods
- 語法:`objectName.methodName()`
- 當使用()呼叫時,屬性將作為函數執行;若不加(),則會回傳該函數定義
- 向物件新增method:
```
object.name = function () {
...
return ...
};
```
- 內建method:toUpperCase()、length等
- object沒有index所以只能用for in或forEach()存取
(詳見for loop)
- object轉array
`Object.values(要轉換的object)`:回傳轉換後的array
### Map(這個MAP不是function)
- 組成:key-value(key可以是任何型態)
- 依照元素插入的順序排序
#### method
- 創建map:
法一:`new Map(由key和value組成的array)`
eg:
```
const fruits = new Map([
["apples", 500],
["bananas", 300],
["oranges", 200]
]);
```
法二:`new Map`並用`Map.set(key, value)`新增元素
eg:
```
const fruits = new Map();
// Set Map Values
fruits.set("apples", 500);
fruits.set("bananas", 300);
fruits.set("oranges", 200);
```
- 修改/增加元素:`map_name.set(key,value)`
- 取出map中key對應的值:`map_name.get(key)`
- map大小:`map_name.size`
- 刪除map中元素:`map_name.delete(key)`
- 查詢元素(true/false):`map_name.has(key)`
- 把map每對元素呼叫執行function:`map_name.forEach(function(value,key){//function內容})`
#### object和map差別

:::
## Event
:::success
- 在網頁中發生的各種交互作用或狀態改變,eg:滑鼠游標碰到、頁面大小改變… → Javascript可以回應這些互動
- 語法:
```
<element event='some JavaScript'>
```
通常要執行的Javascript都是由多行組成,所以通常用呼叫function的方式
eg:
法一:
```
<button onclick="document.getElementById('demo').innerHTML = Date()">The time is?</button>
<p id="demo"></p>
```
法二:
```
<button onclick="this.innerHTML=Date()">The time is?</button>
```
(this代表當前被點擊的按鈕元素)
**↓**

按button會出現現在時間
- 其他Event

:::
## Strings
:::info
JavaScript String用於存儲和操作文本
```html
let text = "John Doe";
```
### Template String
- use back-ticks (``) rather than the quotes ("") to define a string
```
let text = `Hello World!`;
```
- `${...}`提供一種將變數和表達式插入字串的方法
```htmlembedded
<p id="demo"></p>
<script>
let firstName = "John";
let lastName = "Doe";
let text = `Welcome ${firstName}, ${lastName}!`;
document.getElementById("demo").innerHTML = text;
</script>
```

- 允許字串中有表達式
```
<p id="demo"></p>
<script>
let price = 10;
let VAT = 0.25;
let total = `Total: ${(price * (1 + VAT)).toFixed(2)}`;
document.getElementById("demo").innerHTML = total;
</script>
```

- Method
- Length
```
變數.length;
```
- Extract Character(read only,不能改內容)
eg.
1. `at(*position*)` -可以有負的index
2. `charAt(*position*)` -若找不到回傳空字
- Extracting String Parts
eg. `substring(*start*, *end*)`:取子字串
- Upper/Lower Case
- `toUpperCase()`
- `toLowerCase()`
- 連接兩個或多個string
- `concat()`
- 去掉頭尾的空格
- `trim()` -去掉頭尾的空白
- `trimStart()` -去掉頭的空白
- `trimEnd()` -去掉尾的空白
- Padding-補齊/去除到特定長度
- `padStart()`:從前開始補
- `padEnd()`:從後開始補
- 取代字串
- `replace(要被取代的字串,要取代成什麼)` -指取代第一次遇到的字串、大小寫不同
- 常用正則表達式:
`/字串/g`:取代每個字串
`/字串/i` :不分大小寫取代
- `replaceAll(要被取代的字串,要取代成什麼)`-取代每個字串、大小寫不同
要被取代的字串要是”字串”或是/字串/g
- String轉array
- `split()`:切割字串再存為陣列
eg:
`split(“,”)`以逗號分割將每個字放人分別的index中
`split()`將整個字串放入index[0]
`split(“”)`將每個字母切割
- 找出相同的字存到陣列 eg.
- `match()` -可以用”字元”或是/字元/,只會匹配第一個遇到的字
- `matchAll()` -字串要是”字串”或是/字串/g,匹配遇到的所有相同字串
:::
## Number
:::info
- NaN = Not a Number
- `isNaN()` -判斷是否是數字
- `typeof NaN` returns number
- `Infinity`-超出數字最大範圍時回傳Infinity
- `typeof Infinity` returns number
- BigInt
- 超出Safe-Number(from -(253 - 1) to +(253 - 1))範圍的數字,並以字串儲存,不能有小數點
- 宣告:`BigInt(數字)` 、`數字n`
- Min/Max Safe Integers
- `MAX_SAFE_INTEGER`
- `MIN_SAFE_INTEGER`
- 判斷是否是int(true/false)
- `Number.isInteger()`
- 判斷是否是在安全範圍內的int(true/false)
- `Number.isSafeInteger()`
- Method


- `toExponential(要到小數點第幾位)` -將數字轉成科學符號,並回傳String
- `toFixed(要到小數點第幾位)` -將數字四捨五入到小數點後第幾位
- `toPrecision(總共要幾位)` -總共要幾位數字,並回傳String
- `valueOf()` -將不是數字型態的數轉成數字型態
- `Number()` -將不是數字型態的數轉成數字型態
- Property

- `EPSILON`-因為浮點數是取近似值,所以不能直接比較是否相等,要用EPSILON來判斷兩個浮點數的相差值是否小於(大於1的最小浮點數-1),以判斷浮點數的值是否相等
- MAX_VALUE -Javascript可以表示的最大數字,接近無限大,但在數字很大時精確度低
MAX_SAFE_INTEGER -可以被精確表示的最大整數
:::
## Array
### 宣告:
:::info
- 法一:`const array_name = [item1, item2, ...];`
- 法二:`const array_name = [];//之後再給予element值`
*同一個 array中可以存不同型態的 item: object、function、array...*
:::
### array的存取
:::info
- 存取整個array:
直接打array_name: `document.getElementById("demo").innerHTML = (array_name); //此時"demo"的內容會變成array裡所有物件`
- 一個個取出所有元素:
- 法一:迴圈
```
for (let i = 0; i < n; i++) {
//程式碼 }
//做到第n個,全部做完n=array.length-1
```
- 法二:`array_name.forEach() //把每個都做一次`
- 存取各個item內容:
用index取值: `array_name[(index)]`
:::
### array iteration
:::info
- `forEach()`:把array中元素取出來傳入callback function(參數有value,index,array順序固定但index、array不一定要有值)中,不會修改原陣列值,且沒有return
- `map()`:建立一個新陣列,其內容為原陣列中每個元素計算以後回傳結果(所以一定要有return)形成的集合(和forEach()類似差在map()會把結果存到新的陣列中)
- `flatMap()`:先執行完map()再做flat(預設為一級展開,就是把一個陣列中第二層的括號拿掉 eg:[1, 2, [3, 4, [5, 6]]]→[1, 2, 3, 4, [5, 6]])
- `filter()`:建立一個新陣列,且存入的內容會經過篩選(eg:大於某數)
- `reduce()`:將陣列中每個元素(由左至右)和回傳值再次做運算(累加、比較...),function有目前總和、value、index、array
- `reduceRight()`:在由右至左做reduce()
- `every()`(true/false):確認陣列裡面每個元素是否都通過篩選
:::
## Array/object的差別
:::info
* Array和object差別
|| index | 宣告 |
| -------- | -------- | --------------------------------------------------------------------------- |
| array | Text數字 | `array_name = [items];` 若[ ]中只有一個數字代表宣告幾個undefined type的元素 |
| object |名稱(String)| `array_name = new Array(items)`只有一個item要用var宣告 |
:::
### function
:::info
* array轉string:`array_name.toString()`
* 元素數:`array_name.length`
* 排序元素:`array_name.sort()`
* 增加元素(加到最後):
法一:`push(item)`
法二:`array_name[array_name.length]`
* 判斷是否為array:
法一:`typeof array_name`
法二:`array_name.isArray();`
法三:`array_name instanceof Array;`
:::
## For Loop
### for in
:::info
- 用途:存取object/array中property的**key**(但array中不一定會照順序存取)
- 語法:
```
for (key in object/variable in array) {
// code block to be executed
}
```
eg
```
const person = {fname:"John", lname:"Doe", age:25};
let txt = "";
for (let x in person) {
txt += person[x] + " "; //因為是存取key所以要用person[x]才能取得值
}
```
:::
### for of
:::info
- 用途:存取可以迭代的object(eg: Arrays, Strings, Maps, NodeLists)的**值**
- 語法:
```
for (variable of iterable) {
// code block to be executed
}
```
:::
### map
:::success
map() 方法會**建立一個新的陣列**,把原陣列的每一個元素經由function運算後所回傳的結果塞到新陣列。
```
const array1 = [45, 4, 9, 16, 25];
const array2 = array1.map("這邊放function");
//假設function是把數字*2,array2的內容就會是[90,8,18,32,50]
```
- 方法:
1. `const array2 = array1.map((x) => x * 2);`
2. `const array2 = array1.map(myFunction);
function myFunction(value, index, array) {
return value * 2;
}`
3. `var array2 = array1.map(function (x) {
return x * 2;
});`
//`map()`每次用時都會出現新陣列,因此如果不需要新陣列出現的話用`forEach()`之類的就好
:::
### 正則表達式
:::info
* 功能:比對字串
* 語法:/`正則式`/
* 符號
\ → 跳脫符號
. → 任意字元
$ → 以...結尾
^ → 以...開頭(在[]中代表否定 = []內的字都不要)
[] → 可以使用得範圍
* 匹配次數
\* → 任意次數,等同於 {0,}
\+ → 至少一次,等同於 {1,}
? → 零或一次(有或沒有),等同於 {0,1}
?: → 某一區塊重複出現
{m} → m 次
{m, n} → 從 m 到 n 次
* EG
電話號碼:/^09[0-9]{2}-[0-9]{6}/ → 以09為開頭接兩個0-9數字後加上"-"再接6個0-9數字
email:/\^[a-zA-Z0-9]+@[a-zA-Z]+(?:\\.[a-zA-Z]+)+$/ → 以一個以上英文或數字為開頭@一個以上英文字母一組以上的".加多個英文字母"為結尾
:::
### localStorage
:::success
將資料從頁面中的程式碼儲存到Web瀏覽器的儲存空間當中,本來存入程式碼當中的資料,就不會因重新整理頁面或者關閉瀏覽器而消失,可以跨瀏覽器分頁使用且資料無期效限制,將永久被保留
- 存值到localStorage
`localStorage.setItem(key, value)`:
指定物件屬性的 key 以及 value,可以在 storage 物件中加入屬性或修改原本的屬性內容
- 從localStorage取值
`localStorage.getItem(key)`:
輸入屬性的 key,可以得到 storage 物件對應屬性的 value
- 移除資料
- `localStorage.removeItem(key)`:
把指定的屬性從 storage 物件中移除
- `localStorage.clear()`:
清除所有的資料
#### 資料只能為字串!!
localStorage的key和value只接受字串
- 轉成JSON格式的字串
`JSON.stringify(value)`
- 接收字串轉回原本的值
` JSON.parse() `:接收JSON字串轉成物件或值
:::