# 8天重新認識JS 筆記/ 思晨 ## Day1 #### JS簡史 #### 基礎知識 資料型別 1. 變數宣告不能為保留字或是關鍵字 2. ES6後將變數宣告分為常數與參數(const、let) 3. JS為弱型別 所以宣告後不須指定型別 4. 變數宣告沒有賦予值 為undefined 5. 變數沒宣告沒賦予 會呈現 RefrenceError 6. 沒宣告 Var的情況下 會變全域變數 7. Var可以重複宣告 let 會出現錯誤 8. 變數沒有型別 值才有 9. null型別為 object 10. JS型別分為**基本型別**與**物件型別** 11. 物件型別分 null、boolean、number、string、undefined、symbol 【string 字串】 * 多行字串 可用 \ (反斜線)來斷行 * es6 樣板字面值 支援多行字串,直接換行即可 * 也可在樣版字面值裏直接加入運算式 “${2*a+b}” 【number 數字】 * 整數、小數、NaN(not a number)、Infinty、-Infinty * NaN 的型別為 number * NaN 與任何數字相加都是NaN * NaN 不等於**NaN**及 任何**數字所做的數學運算** * 判斷NaN 可以用isNaN()的方式來判斷 **參考資訊** https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/isNaN 【boolean 布林值】 【null 與 undefined】 * null 類似空值的意思 * underfined 未定義 #### 物件 陣列 型別判斷 【object 物件】 * 物件是由零個或多個屬性組成 * 屬性的組成有 key 與 value * value 可以是某個基本型別、物件、function * 運用{}建立物件的方式 稱為物件實字 同樣也是JSON格式的核心語法 * 可透過“.” 或是[]來存取值 **EX:** person.name、person["name"] * **新增屬性與刪除** 若新增屬性 直接“=” 賦予就可以,刪除則用delere **ex:** delete obj.name * 可以用“in”及“hasOwnProperty()”來驗證是否物件中有該屬性 * “hasOwnProperty()”不會沿著原型鏈網上查找 但是“in”會 【Array 陣列】 * 可透過 length 來獲取陣列長度 * length 可隨時被修改 * 陣列中無法取得的數值會變成“undefinde” * 可用“isArray()”來判斷是否為物件 12. 可運用“typeOf”來判斷型別 #### 運算式與運算子 1. 四擇運算 【+號】 * 相加只要有一則為NaN 則相加為 NaN * 相加有字串 則型別一率改為字串 【-號】 * 當減法有一方不是數字時 會將型別自動轉成數字 【乘號】 【除號】 【取餘數(%)】 2. 一元運算子 【遞增與遞減 ++ --】 3. 比較運算子 【相等於與全等於 == vs ===】 * ===較嚴謹 不會自動轉型別 ## Day2 #### 自動轉型的規則 * 如果是布林,會轉為數字 再做比較 * 如果是**字串**與**數字**比較,會先**將字串轉為數字**再做比較 * 如果是物件,則會轉成**基本型別**,再做比較 * NaN不等於NaN * 如果物件比較 都指向同一實體 才會回傳true * 如果兩者都是字串,則會依照字母順序做比較 **指派運算子 逗號運算子 邏輯運算子** * **邏輯運算子** ToBoolean()轉成布林值 是false(falsy值)的有 * Undefined * Null * 空字串“”或是‘’ * +0、-0、NaN * 若是“||” 答案是true 則是回傳第一個 否則回傳第二個 * 若是“&&”答案是true 則是回傳第二個 否則回轉第一個 #### 流程判斷與迴圈 * **條件判斷 (if...else)** * **條件判斷(switch)** switch(判斷條件) case1 : console.log('test'); break; * **三元運算子** (條件)?[運算式1]:[運算式2] * 條件符合 true 則回傳運算式1,否則回傳運算式2 * **for迴圈** * **while迴圈** * break 與 continue 中斷迴圈 * 若是迴圈次數不明確 則用 while迴圈來撰寫更為方便 #### 函式基本概念 * **函式宣告** 與 **函式運算式** * new Function 建立函式(實務上較少運用) * ES6前,切分有效的作用域是function * **Hoisting(提升)** * 變數都盡量在scope的最上方做宣告 * 變數提升只有宣告被提升,函式提升則是整個函式一起提升,所以函式可在創建前呼叫,由於Hoisting的關係,會執行該函式 * let與const / var 的差異 * let與const 作用域為 * 在hosting的情況下 在let與const宣告前呼叫該變數,會出現ReferenceError 在var的情況下則會出現undefined #### JS傳值與傳址 * 基本型別與物件型別 * 基本型別為傳值,物件型別為傳址 * (pass by sharing)當function中的參數,被重新賦予值,外部的變數內容不會受影響 ## Day3 #### DOM與BOM 1. BOM是瀏覽器核心 windows物件 2. BOM是瀏覽器與JS溝通的窗口,不涉及網頁內容本身 3. DOM是控制網頁內容及網頁節點 #### DOM API查找與遍歷劫點 * 透過document.querySelector取得的Nodelist是靜態的,無法即時更新,若要即時更新,要使用document.getElementById 來取得 #### DOM Node的建立與刪除 刪除 修改外觀 * **document.createDocumentFragment()** * 最小化文件物件 * 不是真實的DOM結構 * **document.write()** * **NODE.appendChild(childNode)** * **NODE.insertBefore(NewChild,refNode)** * 在原本的NODE節點前,新增一節點 * **NODE.replaceChild(Newchild,oldNode)** * 在原本的節點上覆蓋一個新節點 * **NODE.removeChild(childNode)** * 刪除子節點 * classList.add()、classList.remove() #### BOM 與 Window 物件 * location與histroy * history.pushState() ## Day4 #### 事件機制原理 1. 事件捕獲 與 事件冒泡 * **事件冒泡** 由觸發區域向上傳遞 * **事件捕獲** 由觸發區域向下傳遞 2. **addEventListener()** * 好處為可以重複指定多個處理器 * 第三個參數,若未指定則為冒泡機制 3. **removeEventListener()** * 移除時,需要設定同一個函式,所以監聽時要確保兩者為同一個函式實體 4. 侵入與非侵入性JS #### 網頁的事件與生命週期 事件種類: **1. 網頁介面相關事件** * load * unload、beforeunload 會在頁面重新整理或是離開時觸發 * error * resize * fullscreenchange * scroll * DOMContentLoaded DOM元素載完後觸發 **2. 滑鼠相關事件** * mousedown/mouseup * click * dbcilck * mouseenter / mousemove / mouseleave / mouseover * mouseenter / moseover 差異處在於mouseover 會傳遞冒泡事件到上層 * mouseover 的觸發時間早於 mouseenter **3. 鍵盤相關事件** * keydown * keypress * keyup * 可用event.keyCode 來判斷使用者目前按下哪顆按鈕 **4. 表單相關事件** * input * 當輸入內容被改變就觸發 * select * change * 當表單元素發生改變時觸發,不同於input,是在離開輸入匡焦點後才觸發的 * submit * 當<form>送出時觸發,通常表單驗證都會在此進行 * reset * 當<form>被重置時觸發 * focus * blur * 當<form>表單元素離開焦點時觸發 **5. 特殊事件** * compsitionstart / compsitionend / compsitionupdate * compsitionstart 輸入框開啟輸入法,正在拼字時觸發 * compsitionupdate 正在拼字或是選字時更改觸發 * compsitionend 選字或是拼字完成時,政要送入輸入匡時觸發 * cut * copy * paste * 常用於使用者複製文章,增加版權警語提示時 **6. 自定義事件** #### 隱藏事件的秘密 * 阻止預設行為 event.perventDefault() * 阻止冒泡事件 event.stopPropagation() * e.target 與 e.currentTarget * 事件指派 可在父層建立監聽機制,配合 e.target 加入判斷機制以達成多個元件綁定 ## Day5 #### 函式與參數 **1. 箭頭函式** * 箭頭函式this強制綁定 沒有自己的this * 當return只有一行時 可以省略"return"及"{}" * 當沒有參數時“()”不能省略,但若只有一個參數 “()”則可以省略 2. call()與apply() * 除了()直接呼叫外 也可以用 call() 與apply()呼叫 ```javascript= const plus=function(numA,numB){ return numA+numB } // 第一個傳入的參數為函式執行的this //用apply 及 call 執行 可以直接替換原本全域的this //call的用法 func.call(null,1,2)//第一個變數為指定的this //apply的用法 (用陣列包覆) func.apply(null,[1,2])//第一個變數為指定的this ``` 【 補充 】 * **bind** * 與apply及call 會立即呼叫函式不同,bind是先定義,等到呼叫該函式才會執行 ```javascript= var fn2 = fn.bind(family,"小明","小美"); fn(); //第一個參數為指定的this ``` **2. arguments物件** * 函式被呼叫時 會創建出arguments物件,這個物件的內容為傳入的參數 * 雖然看起來像陣列但事實為待索引的物件,但可以藉由length來獲取長度 ```javascript= const plus= function(){ let num=0 for(let i=0;i<arguments.length;i++){ num += arguments[i] } return num } //3 plus(1,2) ``` * 箭頭函式無法使用arguments物件 * arguments.callee()指的是目前執行的函式,當我們需要遞迴時,可以透過執行arguments.callee()來完成 **3. 其餘參數** * 箭頭函式 可以用“其餘參數”的方式來取的不確定數量的參數 ```javascript= const plus=(...args)=>{ let num=0 for(let i=0;i<args.length;i++){ num += args[i] } return num } //3 plus(1,2) } ``` * 當函式最後一個以...為命名,會被視為一個陣列 4. 以物件做為參數 5. 參數預設檢查 * ES6 後可以設定預設值 ```javascript= const plus=function(numA=0,numB=0){ return numA + numB } ``` #### 回呼函式(CallBack) 與 立即執行函式(IIFE) 1. **回呼函式** 把函式當作一個參數透過另一個函式來呼叫他 2. **立即執行函式(IIFE)** 運用立即執行函示來確保 i 不會在setTimeout尚未跑完時for迴圈已經執行完畢,立即執行可以保存當下的 i ```javascript= for(var i=0;i<5;i++){ (function(x){ window.setTimeout(function(){ console.log(x) },1000*x) })(i) } ``` #### CallBack 到 Promise 1. 同步與非同步 2. promise物件 ```javascript= function myAsyncFunction(url){ return new Promise((resolve,reject)=>{ //resolve() or reject() }); } funcA().then(funcB).then(funcC) ``` 3. 需要串接多個promise,可以透過.then() 4. 若不需分順序 則由 promise.all()執行 ```javascript= Promise.all([funcA(),funcB(),funcC()]).than(()=>{console.log('')}) ``` 5. promise.all() 任務全部完成才執行 6. promise.race() 任務其中之一完成就會執行 * 由於其中之一跑完就執行,不代表會中斷,全部的function 都會執行順利 7. Async/ Await ```javascript= const funcA=()=>{ return new Promise((resolve,reject)=>{ window.setTimeout(()=>{ resolve('resolveA'); },(Math,random()+1)*1000) }) } async function asyncCall(){ const result= await funcA(); } asyncCall(); ``` #### setTimerout 與 setInterval 理解 EventQueue 1. 非同步與單一執行序 若是在運作中,遇到非同步的函式,會先略過,等到完成才會丟回儲存列 2. 運用 requestAnimationFrame 來代替setTimeout()與setInterval() ## Day6 #### 閉包(closure) * 範圍鏈 scope chain ```javascript= function counter(){ var count=0 return function(){ return ++count } } console.log(counter()()) ``` #### this in JS 1. 大多數的時候 this 指的是呼叫 function 的物件並不是function本身 2. 沒有明確指定的情況下 this 就會指定為 window 3. event.currentTarget 4. 預設綁定 隱含式綁定 顯示綁定 new字綁定 5. Simple Call(立即函式、回呼函式)的 this 通常指向為 window 6. 盡量不用 simple call的 this,因為其本質為“undefined” 7. 如果回呼函式需要綁定 在函式外層先綁定this ```javascript= var family={ myName:'小明家', callName:function(){ var self=this;//在外層先綁定 setTimeout(function(){ console.log(self.myName) },1000) } } family.callName(); ``` 8. **嚴格模式** 在函式裡面加入字串“use strict”即為嚴格模式 9. **箭頭函式的this**是強制被綁定的,如果要正確指向,要確實將函式宣告在該物件內部 10. 當函式前增加一個new來創件時,this會自動指向新創建的物件 11. ## Day7 #### 深入理解JS物件 1. new、Object.create()建立物件 #### 內建物件與包裹器 1. js內建型別分為 基本型別 與 物件型別 #### 物件原型鏈 與繼承 1. Object.setProtoypeOf() 2. 同一物件無法繼承兩種原型 3. 當物件實體與原型皆有相同屬性時,會優先選取自己的方法與屬性 4. **查詢屬性為物件本身 或是原型鏈上的方式** ```javascript= console.log("cutter" in rockman)//如果是原型鏈上的使用 in console.log(rockman.hasOwnProperty('cutter'))//如果是檢查物件本身 用 hasOwnProperty ``` 5. 當函式被建立時 都有一個原型,叫做 prototype 6. 原型可以利用 .prototype 的方式來新增屬性,就能讓每個物件都繼承圓形新增的屬性及方法 7. 可以運用Object.getPrototypeOf()來獲取某個物件上的原型 8. 靜態方法 static、extends、super 9. getter、setter #### ES6 Class 語法糖 ```javascript= //es6 class 寫法 calss Preson{ constructor(name){ this.name=name } greeting(){ return 'Hello!My name is'+ this.name+'.'; } } const Mark= new Preson('Mark'); Mark.greeting(); //'Hello!My name is Mark.' ``` 1. 函式會被提升,但是Class不會被提升 (type of class創造的物件 是 function) 2. 還是可以用 .prototype ## Day8 #### Page 到 Application 前端生態圈演變 1. 簡單的專案變得複雜 複雜的專案變得更好管理 2. DOM元素+WebUI、網頁模板引擎 3. MVC與MVVM 4. 後端的V等於前端的M 【補充】**前端MVVM架構** Model:管理資料來源如API和資料庫 View:顯示UI及接收使用者動作 ViewModel:從面兩者取出所需的資料![](https://i.imgur.com/benAKHL.png) 資料來源:https://ithelp.ithome.com.tw/articles/10192829 5. **網頁模組化** frame、frameset => 模板引擎 =>前後端分離 web component 6. 過去關注焦點以類別(結構、樣式、行為)區分 現在以元件區分 7. **css 架構與命名學** #### JS 現在與未來 1. es6語法 箭頭函式、let const、class語法糖、ES6 Generator、