此為龍哥影片內的筆記, 請由左側選擇想看的部分做查詢 此筆記不含實作練習部分, 該部份請自行看影片與練習 # 名詞 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(”位置”, 該變數)來插入 ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/2ab50771-fd84-4380-b24c-087641c2be2b/cb4e0354-aa93-4c70-a976-5839cf63cf0c/Untitled.png) # 事件 瀏覽器在執行的時候會發生許多「事件 (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 所衍生的)