此為龍哥影片內的筆記, 請由左側選擇想看的部分做查詢
此筆記不含實作練習部分, 該部份請自行看影片與練習
# 名詞
EMCA : European Computer Manufacturers Association 歐洲電腦製造協會
TC39 : Technical commitee 39 (EMCA 底下的一個委員會)
此委員會有提出 ECMA-262 (一種標準化規格)
EMCAScript : 根據 ECMA-262 規範所制定的程式語言規格
ES6 : EMCAScript 6
# 前置基礎
JS 主要寫在
- 瀏覽器的 console (主控台)
- 網頁
- 寫在 <script> 標籤裡或外部檔案
- 放在 <head> 標籤裡
- 放在 <body> 標籤裡
- 直接寫在某些 html 的 dom 元素上
註解
- 單行用 /
- 多行用 /* */
分號
盡量不要自動安插分號,電腦會猜錯
等號
一個等號 : 在設置變數中為 指定 (assing) 的意思
# **變數、常數、資料型態**
## 宣告變數
命名規則 :
- 可用英文或數字,但開頭第一個字母不可以是數字
- 不可使用保留字
- [保留字](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#keywords)
| break | default | for | return | var |
| --- | --- | --- | --- | --- |
| case | delete | function | super | void |
| catch | do | if | switch | while |
| class | else | import | this | with |
| const | export | in | throw | yield |
| continue | extends | instanceof | try | |
| debugger | finally | new | typeof | |
- 注意大小寫有區別
- 望文生義
- 慣例 : 駝峰式命名法
變數 (variable) : 像是容器來指示出”值 (value)”,而值本身可以是 數字、文字、布林值……等。
用 const 宣告常數 : 常數不是不能改,而是不能「重新指定 (re-assign)」
### 未定義與沒有定義
未定義 (undefined) : 存在,但沒有定義
沒有定義 (not define) : 連存在都不存在
### 變數提昇 (Variable Hoisting)
未宣告變數,但後面有宣告並賦予值時。前面未宣告的變數會先以未定義 (undefined) 存在,在後面宣告時才有值。~~( 使用 var 宣告時,用 let 宣告一樣會出現錯誤,但 let 還是有變數提昇的狀況 )~~
(因 JS 是屬兩段執行,第一次會先掃過變數,第二次才是正式執行賦值 (簡單解釋版))
## let, const, var 如何選擇
- 能 const 就用 const, 不能用 const 就用 let
- var 也可以用, 但它的範圍 (Scope) 比較大
- 千萬不要沒宣告就使用,會造成全域物件汙染
# 資料型態
變數本身是沒有型態的
分為兩大類
型態間可以轉換,如 : a =123; b = String (a); 此時 b 的型態就會變成字串
## 原始型別 (Primitive Type)
- 數字 (Number)
同四則運算,並括號內先運算
- a++ 與 ++a
a++ 為 a 的值之後 +1
++a 為 a 的值先 +1 後回傳 a
- NaN : Not a Number 不是一個數字的意思
用來代表”不是數字”的**數字** (所以 NaN 的本質是數字)
- 字串 (String)
用單雙引號都可以, `` (此符號稱為 backtick ) 也可以,更可串接變數
- 真假值, 布林值 (Boolean)
只有 true 跟 false
- 空值 (Null) : 表示不存在,但用 typeof 去查會`顯示為 object`
- 未定義 (Undefined)
- 符號 (Symbol)
## 物件型別 (Object Type)
- 陣列 (Array)
- 函數 (Function)
- 物件 (Object)
### 強制轉型 (Type Coercion)
# 流程控制
## IF
### if
給予一個條件,若符合條件便執行某件事,若不符合則不執行
```jsx
if (條件) {
符合條件便執行某事
}
```
### if … else …
符合條件執行某事,否則執行其他的事情
```jsx
if (條件) {
符合條件執行
} else {
不符合條件則執行另一件事
}
// 若要增加
if ( ){
} else if ( ) {
} else {
}
```
### 三元運算子
雖然可以使程式碼簡短,但要注意可讀性
### Switch
依多事件去判斷要執行那個事情
```jsx
let example = 值
switch (example) {
case 條件1的值:
執行某事
break
case 條件2的值:
執行某事
break
default: //default 可寫可不寫,但建議要
某事
break
}
```
## 布林值
只有 true / false 沒有其他
### 視為 false 的值
0 / undefind / null / 空字串 / NaN
## 邏輯運算
### and / or / not
前後都要成立,寫法為 &&
前後其中一邊成立即可,寫法為 ||
代表”不等於”,寫法為 ! 如 : !== (不等於)
## 補充
prompt (瀏覽器會跳出視窗請使用者輸入)
可設定一個 變數 = prompt()
由此獲得使用者輸入的值
如 : let value = prompt (”請輸入值”)
## 迴圈 Loop
### For 迴圈
- 寫法
```jsx
for (let 變數 = 值; 變數 < 次數 ; 變數 = 變數 + 1 /* 每次動作後變數的值加1 */ ){
每次要執行的動作
}
```
中間為執行條件, 同 while 滿足條件便會執行
### While 迴圈
- 寫法
```jsx
while (條件 /* 若符合條件就會執行 */) {
每次要執行的動作
}
```
### 比較
數量明確建議用 FOR
但原則上兩者都可以互換。
## 補充
重複字串 ( .repeat() )
> a.repeat(4)
< aaaa
> ruby.repeat(3)
< rubyrubyruby
# 函數
function 本身是值也是一種物件
## 定義函數
1. 用 function 宣告 並將此函數命名,在後方括號加入參數 (Parameter,如果有的話) 最後用大括號將欲直行的行為定義,模式如下 :
function 函數的名子( 參數 ) {
此函數要執行的行為
}
要使用時,用名子加括號即可,如 : 函數的名子()
- 例子
```jsx
function funcName(){
console.log("範例")
}
```
2. 可先宣告變數名稱,後將此變數指定函數給它,如 :
const 函數的名子 = function(參數) {
此函數要執行的行為
}
- 例子
```jsx
const funcName = function(){
console.log("範例")
}
```
可改寫為 [箭頭函數 (Arrow Function)](https://www.notion.so/JavaScript-b4256c1ba56b4abcb8dbcb7e77bb496c?pvs=21) ,如 :
const 函數的名子 = () => {
此函數要執行的行為
}
- 例子
```jsx
const funcName = () => {
console.log("範例")
}
```
### 兩種宣告差異 (1跟2)
下方用宣告變數並指定函數的方式,此函數為「匿名函數 (Anonymous Function)」
使用上沒有差異,唯一不同的是 : 使用匿名函數若在宣告前執行,會發生錯誤。
### [箭頭函數 (Arrow Function)](https://www.notion.so/JavaScript-b4256c1ba56b4abcb8dbcb7e77bb496c?pvs=21)
不只是 function 的縮寫,與 this 有關
## 使用函數
函數名要加上 () 才會執行。
### 參數 vs 引數 (Argument)
引數為執行時所帶入的參數,該參數的名子為引數,如圖所示 :
function 函數名子 (參數) {
欲執行的指令
}
函數名子 (引數)
- 例子
```jsx
function 函數名子 (參數) {
console.log(參數)
}
函數名子(引數) // 螢幕會印出 引數
```
### 加入參數
可在括弧內加入參數,便可以改變執行的動作
- 例子
```jsx
function funcName(method){
if (method == 1) {
console.log("參數為1")
} else {
console.log("參數不為1")
}
}
> funcName(1)
< 參數為1
> funcName(54654)
> 參數不為1"
```
參數的個數;
若參數有設置三個,但引數的數量不對,狀況會如下 :
有少,則少的那個位置的值會為 undefined
有多,則會被無視
若參數有設置預設值,如 :
```jsx
function sayHi( a, b, c = “hi”) {
console.log( a, b, c)
}
sayHi() //undefined, undefined, hi
```
## 回傳值 (Return Value)
函數最後要用 return 來將結果回傳 (代表這個函數最後的結果),如 :
- 例子
```jsx
function isAdult(age){
if (age >= 18) {
return true
} else {
return false
}
}
isAdult(x) // 此時會依帶入的 x 來告訴你是 T 還是 F
```
在函式內若碰到 return 就會將控制權交還回去(可想成此函式直接變成回傳的那個值),所以在下面的動作就不會執行。
所有的函數**都有回傳值**,即便沒有寫 return 也會回傳 **undefined**
# 陣列 (Array) 與物件 (Object)
## 陣列
用 中括號 定義陣列,如 : let array = [a, b, c]
可在裡面放入任何值,甚至再放入陣列也可以,稱為「多維陣列」(常見為兩層、三層以上則為少見)
### 陣列操作
陣列長度 : array.length //此為陣列內有幾個元素
取得元素 : 可用索引值 (index) 來操作,陣列從 0 開始操作 (第一個值)
- 範例
```jsx
let array = ["A", "B", "C", "D", "E"]
console.log(array[0]) // 會印出第一個值 A
```
新增元素 : push, pop, shift, unshift
可用 push (從最後面新增) 或是 unshift (從最前面新增)
- 範例
```jsx
let array = ["A", "B", "C", "D"]
console.log(array) // 會印出 ['A', 'B', 'C', 'D']
array.push("X")
console.log(array) // 此時會印出 ['A', 'B', 'C', 'D', 'X']
array.unshift("Y")
console.log(array) // 此時會印出 ['Y', 'A', 'B', 'C', 'D', 'X']
```
可用 pop (從最後面抽出) 或是 shift (從最前面抽出)
- 範例
```jsx
let array = ["A", "B", "C", "D"]
console.log(array) // 會印出 ['A', 'B', 'C', 'D']
array.pop()
console.log(array) // 此時會印出 ['A', 'B', 'C']
array.shift()
console.log(array) // 此時會印出 ['B', 'C']
```
修改元素 : 索引值, splice
直接使用索引值指定某個位置的值作修改
- 範例
```jsx
let array = ["A", "B", "C", "D", "E"]
array[1] = "X"
console.log(array) // 會印出 ['A', 'X', 'C', 'D', 'E']
```
使用 splice, 在後方可設定三個參數;從哪開始,刪除幾個,放入值
- 範例
```jsx
let array = ["A", "B", "C", "D", "E", "F"]
array.splice(1, 2, "X")
console.log(array) // 會印出 ['A', 'X', 'D', 'E', 'F']
array.splice(3, 0, "Y")
console.log(array) // 會印出 ['A', 'X', 'D', 'Y', 'E', 'F']
```
組裝陣列 : concat
- 直接看範例
```jsx
let array1 = ["a", "b", "c"]
let array2 = ["x", "y", "z"]
let newArray = array1.concat(array2)
console.log(newArray) // 會印出 ['a', 'b', 'c', 'x', 'y', 'z']
```
### 相關函數
陣列內有無某元素 :
.indexOf( ) → 小括號內的值在陣列當中的索引值是多少,若有多個相同元素則會回傳第一個找到的索引值,若此元素不存在則此索引值為 -1。
.includes( ) → 小括號內的值是否存在於陣列之中。依具有無回傳 true / false ;但 IE 不支援。
- 範例
```jsx
let array = ["A", "B", "C"]
console.log(array.indexOf("B")) // 會印出 1
console.log(array.indexOf("X")) // 會印出 -1
console.log(array.includes("B")) // 會印出 true
console.log(array.includes("X")) // 會印出 false
```
印出陣列內的每個元素 :
用 for 迴圈印出
- 範例
```jsx
let array = ["A", "B", "C", "D", "E", "F"]
for (let i = 0; i < array.length; i++){
console.log(array[i])
}
```
forEach → 後面接一個 function (此函數稱為 「[callback 回呼函數](https://www.notion.so/JavaScript-b4256c1ba56b4abcb8dbcb7e77bb496c?pvs=21)」),forEach會將陣列的值一個一個的丟入此函數執行。
- 範例
```jsx
let heros = ["A", "B", "C", "D", "E", "F"]//建議外面的陣列英文名為複數
heros.forEach(function(hero){ //則forEach後的函式參數設定名用單數
console.log(hero) //表示為將陣列的每個值,各自都投入函數內執行
}) //故此例印出的皆是單一個值。
//將回呼函式的形式改寫成箭頭函式也可以,如下
heros.forEach((hero) => {
console.log(hero)
})
```
找尋符合條件的元素 :
.find() → 在後面的括號內放入 function 並會將值迭代
find 只會找第一個符合的就停止, 若沒回傳就停下
- 範例
```jsx
let array = ["AA", "B", "CCC", "DD"]
array.find(function(value){
if (value.length >= 2) {
console.log(value)}
}) // 此時會分別印出 AA, CCC, DD (因為是迭代,所以會印出三行(作三次的意思)
//若改寫成
let val = array.find(function(value)){
return value.length <= 2
})
console.log(val) //只會顯示 AA (因return 會中止迭代
//若是都找不到, 則會回傳 undefined
//新版
const a = [1, 2, 3, 3, 3, 3, 4, 5, 6]
const result = a.find((x) => {
console.log(x) //只會出現 1, 2, 3 就停下來了
return x == 3 // 此時result的值為 3 (第一個的3)
})
```
對某個元素作些事,後蒐集成「新的陣列」
- .map 範例
```jsx
let array = ["A", "B", "C"]
let result = array.map((h)=>{
return h.repeat(5)
})
console.log(result) // [AAAAA, BBBBB, CCCCC]
```
對每個元素作判斷,將符合條件的元素蒐集成「新的陣列」
- .filter 範例
```jsx
let array = ["AAAA", "B", "CCC", "DD", "EEEEE", "FFFF"]
let result = array.filter((h) => {
return h.length >= 4
})
console.log(result) // ['AAAA', 'EEEEE', 'FFFF']
```
將矩陣內的值累加 : 後方接兩個參數,第一個是累加值 (起始值 / 目前總和的值),第二個為每次丟入的值,後方函數
.reduce() → 後方接兩個參數,第一個是累加值,第二個為每次丟入的值;並於後方函數設定第一次的累加值,若沒設定則會拿第一個值當第一次的累加值
- .reduce 範例
```jsx
/*格式為
array.reduce(function( acc/累加值.aka目前加總的值/ ,cv/現在的值.aka這次要丟入動作的值/){
return acc + cv
}, acc/此參數要放入第一次起始的累加值/)
*/
let array = [5, 2, 8, 3, 3, 1] // 此陣列加總值為 22
let result = array.reduce((acc, cv) => {
return acc + cv
}, 20) // 若此處 20 的設定為 0, 或未設定則答案會是 22
console.log(result) // 會印出42
```
### 參照
```jsx
let a = [1, 2, 3]
let b = a
console.log(b) //[1, 2, 3]
b[0] = "x"
console.log(a) //['x', 2, 3]
console.log(b) //['x', 2, 3]
let c = 1
let d = c
console.log(d) // 1
c = 2
console.log(c) // 2
console.log(d) // 1
```
## 物件
與陣列的差別 : 物件有屬性跟行為
用 大括號 定義物件,並設定 key + value 並且每一組用逗號隔開,如 :
```jsx
const dog = {
name : "富貴",
color : "白色",
attack : function (){
console.log ("汪汪!!!")
}
}
```
呼叫方式為
1. 物件名.key 如 : [dog.name](http://dog.name) // 會顯示富貴
2. 物件名[”key”] 如 : dog[”name”] // 中括號裡面需用字串
增減屬性
- 新增屬性 : 直接打出來設定即可,如 : dog.type = “馬爾”
- 刪除屬性 : 用關鍵字 delete ,如 delete dog.age
# DOM (Document Object Model)
DOM : 文件物件模型
需抓取 html 元素時可用 getElement 或是 querySelector
## getElement 系列
須帶入該元素的 ID 或是 ClassName
document.getElementById ( ) // 括弧內放欲選取的元素 ID 名
document.getElementByClassName ( ) // 括弧內放欲選取的元素 class 名
## querySelector 系列
依 CSS 選取器的方式選取,前綴的符號 ( # 或 . ) 不能省略 (因要表示選取哪個層級)
document.querySelector ( ) // 選取 ID 用 # 字號;選取 class 用 . 符號,如 : #title
document.querySelectorAll ( )
## 選取細談
1. 若依 id 去取,都會是元素 (一個),如 :
let d1 = document.getElementById( ”ex-1” )
let d2 = document.querySelector ( ”#ex-1” )
console.log(d1) 跟 console.log(d2) 都是一樣的東西
2. 若依 class 去取,會得到元素們 (全部),如 :
let t1 = document.getElementById( ”ex2” )
let t2 = document.querySelector ( ”.ex2” )
則會得到
console.log(t1) // HTMLCollection
console.log(t2) // NodeList
此二者很像,但不一樣
- 用 getElement 所抓出來的元素們為 HTMLCollection,其意涵為「元素」
而 querySelector 則是 NodeList,其意涵為「節點 (node)」
本質上是不同東西,但此二者同為集合 (非陣列),但亦有所不同
- 所以抓取元素,且不只有一個元素時,此時抓取出來的資料會是「一個集合」,很像陣列,但不是陣列,所以大部分的陣列函數不能使用
若頁面有多個同名 id ,只會抓取第一個元素做操作 (要避片命名同一 ID )
HTML 的標籤 id 屬性,若在JS內無設定變數,可直接用此 id 名稱當作 「變數」 **但絕對不要這樣用**
element 與 node 差別 :
element 本身就是一種 node 但是是特別版本的 node ,所以節點的功能元素都有,盡量都使用 element 的方式
## DOM 操作
### 動態插入標籤 (由 JS 插入 HTML 標籤)
1. const h = document.createElement(”標籤名”) → 先設置變數並創立標籤,同<標籤></標籤>
2. h.textContent = “hi” → 並在標籤內插入文本,同 <標籤>hi</標籤>
3. someDiv.appendChild(h) → 創立的標籤與文本只存在於記憶體中,需再放入其他元素之中使其渲染出來,如其他的 div 元素等,此新增元素則會放在最後面。
簡單說, 創造元素(標籤) → 輸入內文 → 再放入其他已存在的元素之中
### 刪除DOM
1. 先抓取欲刪除的元素的父元素
2. 用 父元素.removeChild( ) 來將其刪除
3. 或是 該元素.remove 刪除 即可
### 找尋 元素
找父層 : 該元素.parentElement 或是 該元素.parentNode
找子層 : 該元素.childNodes 或是 該元素.children
找平行層 : 該元素.previousElementSibling (前一個) / 該元素.nextElementSibling (後一個)
若是以取 node 的方式為 : 該元素.previousSibling (前一個) / 該元素.nextSibling (後一個)
### 指定位置安插 DOM
1. 父元素.insertAdjacentElement(”位置” , 要插入的元素)
如 : ul.insertAdjacentElement(”beforeend” , li) // 會排在達爾後面
2. 或是將標籤已文字設為變數,再用父元素.insertAdjacentHTML(”位置”, 該變數)來插入

# 事件
瀏覽器在執行的時候會發生許多「事件 (event)」,如 : 點擊、滑鼠移動……等。
## 監聽器
若瀏覽器需要知道發生了什麼事件,則需要設置事件監聽器 (Event Listener)
```jsx
//假設 html 檔案內已有設置按鈕 <button id="btn">按鈕</button>
//回 JavaScript 的檔案內,先將按鈕標記出來
const btn = document.querySelector("#btn")
//替此按鈕加上監聽器
btn.addEventListener("click", funtion(){ // 第一個寫監聽什麼事件(此處為按下 click )
console.log("已按下按鈕") // 第二的地方將函數設為引數,表示按下後執行該事情
})
```
### 回呼函數
此函數為非同步的一種;簡而言之,當前置事情發生的時候,再執行該函數事件即可
### 執行 JavaScript 前置細項
若將 JS 放在 HTML 的 <head> 標籤內,因網頁尚未解析 <body> 而使元素不存在而變成空值 (null) 而無法掛上監聽器。解決方法有四 :
1. 在 html 最尾端再載入 .js
2. 監聽頁面,待 DOM tree 建立完成後再去執行其他事件
- 範例
```jsx
document.addEventListener("DOMContentLoaded" , () => { //寫在第一行,表DOM tree完成後再執行後方函數
//此處即可寫入用 querySelector 去抓元素
})
```
3. 欲執行的事情寫在 DOM 上 (不好維護並且無法重複利用,不建議這麼做)
4. 在 HTML 的 <script> 標籤內 加入 defer 代表延遲載入
- 範例
```jsx
<script src='scripts/app.js' defer></script>
```
## 直接在物件上設定事件 (on 系列)
在按鈕上直接加入 ”被點擊時” 的狀況,如 : btn.onclick = function (){ console.log(”被點擊了”)}
此寫法跟監聽器沒有差別,但若有重複的情況,只會有最新的被反應出來 (前指令會被覆蓋)
而監聽器則可以疊加狀態,觸發時皆會執行。
## 預設行為
像超連結的預設行為會將頁面轉置該超連結的網站,但若只是想確認該「點擊」事件有無正常運作,則可以使用 preventDefault 來停止預設行為
- 範例
```jsx
const link = document.querySelector('#link') // 此處假設 html 已有設置 ID 為 link 的超連結標籤
link.addEventListener('click', (e) =>{ // 此處的 e 沒有作用,只是代表點擊這件"事件"
e.preventDefault() //此處意為「預防點擊後的預設行為」,也就是 link 的跳轉頁面,故點擊後不會跳轉
console.log("以點擊按鈕")
})
```
# ES6 / ES2015 語法補充
## 字串與變數組合
加入反單引號 (backquote / backtick) : 使字串內可加入變數,如 :
ES6 之前 : console.log( ”你好,我的名子是” + name + “,今年” + age + ”歲” )
ES6 之後 : console.log( `你好,我的名子是 ${name},今年 ${age}歲` )
## 箭頭函數
- 例子
```jsx
const addNumber = function (a, b) { //前,普通的匿名函式寫法
return a + b
}
// 下為改寫箭頭函式
const addNumber = (a, b) => {
return a + b
}
// 若該函式只有一行,更可將 return 省略
const addNumber = (a, b) => a + b
```
但箭頭函數不是一般 function 的簡寫
## 物件簡寫
- 如果 key 跟 變數的名子 一樣,可以只寫一個代表
```jsx
let name = "富貴"
let age = 10
let dog = {
name,
age,
}
```
## 解構
- 可一口氣將物件的值,分別指定變數,函式也可以
```jsx
const dog = {
name: "富貴",
age: 10,
}
/* 原本若要拿出物件屬性會依以下
let name = dog.name
let age = dog.age
console.log(name, age)*/
let { dogName, age } = dog //解構寫法 (將 key 的 name 當中的值指定變數給 dogName,age 的值指定給 age
console.log(dogName, age) //與上方結果相同
```
## 點點點 (…)
### 展開
- … 在陣列裡有展開的效果
```jsx
const H1 = ["1", "2", "3"]
const H2 = ["X", "Y", "Z"]
const HAll = [...H1, ...H2] //效果等同 H1.concat(H2)
console.log(HAll) // ["1", "2", "3", "X", "Y", "Z"]
```
### 剩下全收
- 將沒指定到的參數通通含括,也可用在函數,如 :
```jsx
const array1 = ["a", "b", "c", "d", "e"]
//用解構來定義 na1, na2 兩個新變數
let [na1, ...na2] = array1
console.log(na1, na2) // a ["b", "c", "d", "e"] 分為 a 跟 剩下所組成的陣列
//函數也可以
function sayHello(user, ...other){
console.log(user)
console.log(other + "YO")
} //正常只會回應 '1', '2',剩下拋棄,加... 則會依第二個處理
sayHello('1', '2', '3', '4', '5') // 1 跟 2, 3, 4, 5YO (若沒加YO 則會回傳 1 跟 陣列['2', '3', '4', '5'])
```
# 抓取網路資料
[API](https://medium.com/itsems-frontend/api-%E6%98%AF%E4%BB%80%E9%BA%BC-restful-api-%E5%8F%88%E6%98%AF%E4%BB%80%E9%BA%BC-a001a85ab638) (Application Programming Interface) : 應用程式”**介面”**,定義多個軟體中介之間的互動並可進行呼叫 (call) 或請求 (request)。
## 資料存取的方法
- GET
- POST
- PUT
- PATCH
- DELETE
### RESTFul (Representational State Transfer) 表現層狀態轉換
REST 是一種設計風格,RESTful 只是轉為形容詞,此風格主要由三種元件組成 :
1. 名詞 (Nouns) : 定義資源位置的URL
2. 動詞 (Verbs) : 對資源要做的動作 (會將動作藏在 HTTP 的 Method 裡面)
3. 資源呈現方式 (Content Types) : 資源表現方式,目前最常用的為 JSON
### 資料傳輸的格式
- XML
- CSV
- JSON (JavaScript Object Notation)
- AJAX (**A**synchronous **J**avaScript **a**nd **X**ML) 非同步JS與XML技術 : 非語法或技術,而是技術的綜合體。
### 同步 vs 非同步
同步比較像打電話,非同步像傳訊息。
可參照下方 async / await
### CORS (Cross-Origin Resource Sharing) **跨來源資源共用**
一種存取機制,防止有心人士惡意存取資料
基本上無法解決,只能請對方開啟 CORS
## 使用 XMLHttpRequest 函數
- 1.先定義 req 物件 (由 XMLHttpRequest 由此物件來取得伺服器端的資料)
2.發出 request (請求),需叫用 HTTP request 類別的 open() 及 send() 兩個方法
3.設置監聽器,只要請求出去,便會加資料抓回來
4.將資料轉換成 JSON 格式
5.此時可用陣列操作物件來使用資料 (印出資料抬頭等)
```jsx
const api = ' api網址 '
//STEP 1
const req = new XMLHttpRequest()
//STEP 3
req.addEventListener('load', () =>{ //此時回傳的是"字串",需轉換成 JSON 物件
const posts = JSON.parse(req.responseText) //STEP 4 將其轉換成 JSON
posts.forEach((post) => {
console.log(post.title)
})
})
//STEP 2
req.open('GET', api)
req.send()
```
## 使用 fetch 函數
- 1.直接使用 fetch 抓取 api ,並 (依該回傳資料繼續動作用 then) 依抓取的資料 (Promise 物件) 改由 JSON 格式回傳回來
2.再繼續由該 JSON 物件,依陣列操作方法操作 (範例內為印出標題抬頭)
```jsx
const api = ' api網址 '
//STEP 1
fetch(api).then((response) => {
return response.json()
}).then((data) => { //STEP 2
data.forEach((d) => {
console.log(d.title)
})
})
```
## 使用 async / await 的寫法
- await 必須在 async 的 function 裡面,此為非同步的寫法。
正常程式為一行一行執行,但此寫法會等待資料後再執行
如例子,會在畫面先呈現 “此行會先行” 而不是抓回來的 title,當 title 抓回來後,便會在執行並出現在主控台。
```jsx
const api = ' api網址 '
async function getPost() {
const response = await fetch(api)
const posts = await response.json()
posts.forEach((post) => {
console.log(post.title)
})
}
getPost()
console.log('此行會先行')
```
# jQuery
1. 可使用檔案下載後再載入,或是用 CDN 的方式載入框架
2. 其好處是若瀏覽器不支援某些 JS 用法 jQuery 可提供類似方法應對
3. 基本上都是以 $ 開頭來執行
- 如 : 開頭待 DOM 解析完成可改用 jQuery 改寫
```jsx
document.addEventListener("DOMContentLoaded",() => {
}
// jQuery 改寫為
$().ready(() =>{
})
```
選取元素 : 以 ID 為 hero 為例 const hero = $(”#hero”)
## 抓取資料的方式
- 用 $ajax 的方式
```jsx
const url = ' api網址 '
//STEP 1 (先設立物件,此處[用ES6的語法](https://www.notion.so/JavaScript-b4256c1ba56b4abcb8dbcb7e77bb496c?pvs=21))
$.ajax({ url }).done((posts)=>{
console.log('載入 DOM 完成後,顯示此行')
posts.forEach(post => { //STEP 2 該回傳值已是JSON格式
console.log(post.title)
})
})
```
## jQuery vs JS/ES6
普通網站 jQuery 就足夠了,Vue 跟 React 適合更高互動的網站。但 ES6 以後基本上都很好寫,支援度也夠,就可以斟酌
### Vanilla.js 香草 JS
效能最好,跨瀏覽器支援度高 (就是原生的 JS ,所有的東西都是原生 JS 所衍生的)