JavaScript - dashing dashshound
下周工作開始要用到 JavaScript, jQuery, HTML, CSS,特此複習
🦊Basic_1
變數
第一個字母必須為英文字母、底線_、錢字號$
後面可接英文字母、底線_、錢字號$、數字
大小寫有區別
關鍵字、保留字不能當變數名稱,詳閱MDN
JavaScript 1.3 起支援Unicode,可用中文(盡量避免)
ES6之後可用var(變數)、let(作用範圍與var不同)、const
所有沒透過var宣告的變數,都會自動變成全域變數
|
|
已經被 var 宣告過的變數可以再次被宣告 [合法]
|
|
透過 let 宣告的變數不能被再次宣告
|
|
變數資料型別
變數本身不帶有資料型別資訊,其中的值/物件才有
變數沒有型別,值才有
JavaScript支援型別
- 基本型別 Primitives
- string, number, boolean, null, undefined
- Symbol (ES6之後多的型別)
- 物件型別 Object
可以用 typeof
運算子協助判斷型別
|
|
xxx例外
|
|
String 字串
沒有 char(字元)
字串用 ’’ 或者 "" 包夾住,單引號雙引號在JavaScript裡面沒啥差異
如果單引號裡面有包單引號,可用\
跳脫字元或者改用雙引號包起來
|
|
多組字串可用+
連接
|
|
多行字串可用\
(反斜線)連接
|
|
String literal 樣板字面值
使用反引號` 包覆字串,由一般字串、$、{ } 組成,提升以下靈活性
-
支援多行字串
1 2 3 4 5 6 7
var bienvenueV1 = '1st row \ 2nd row \ 3rd row'; var bienvenueV2 = `1st row 2nd row 3rd row`; // 不用再加 \ 符號換行
-
允許變數直接嵌入字串
可以用
${}
取代使用+
做字串連接也可以內嵌運算式
1 2 3 4 5 6
var age = 23; var str = `I am a ${age} year-old engineer.`; var a = 5; var b = 10; console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`);
number 數字
boolean 布林值
null 以及 undefined
物件、陣列、型別判斷
Object 物件
物件及屬性
物件屬性存取
屬性新增
屬性刪除
判斷屬性是否存在
Array陣列
typeof 型別判斷
如何判斷是否為陣列
運算式與運算子
Expression 運算式 & Operator 運算子
四則運算
一元運算
比較運算
🦊Basic_2
自動轉型規則
流程判斷迴圈
函式基本概念
傳值還是傳址
JavaScript @ browser (1st)
瀏覽器的物件模型:DOM、BOM
透過 DOM API 查找&遍歷節點
document.getElementsBy**
、document.querySelector
/document.querySelectorAll
差異
document.getElementById
,document.querySelector
取得的只會有一個元素/節點,不會有index與length屬性document.getElementsByXXX
回傳HTMLCollection,document.querySelectorAll
回傳NodeList- HTMLCollection 收集HTML element節點
- NodeList 除了收集HTML element節點,也包含文字節點/屬性節點
- 這兩種都可以用陣列索引的方式存取內容
- HTMLCollection/NodeList 大部分情況下是即時更新的,但透過document.querySelector/document.querySelectorAll 取得的 NodeList 為靜態的
Example
1
|
|
2 改成document.querySelector寫法
|
|
DOM Node 建立、刪除、修改、外觀
document.createElement(tagName)
建立一個新的元素,再搭配appendChild()
、insertBefore()
或replaceChild()
等方法將新元素加入到指定位置
也可以對新元素設定屬性
|
|
document.createTextNode()
建立文字節點的方法,直接在方法加入字串
此方法跟createElement()
一樣,在加入到某節點之前我們看不到
|
|
document.createDocumentFragment()
操作DocumentFragment與直接操作DOM最關鍵區別:
- DocumentFragment不是真實的DOM結構
- DocumentFragment的變動不會影響目前網頁文件,也不會導致回流(reflow)或引起任何影響效能的情況發生
- 如果需要進行大量DOM操作,用DocumentFragment的效能會比直接操作DOM好很多
|
|
document.write()
-
可以輸入單純的字串或者HTML標籤
1
document.write("<h1>Jean Jing Jingle</h1>");
也可以用來新增script標籤,但要注意結尾標籤寫法
<\/script>
1 2 3 4 5 6 7
//</script>會變成目前script區塊的結束,導致錯誤 document.write("<script type=\"text\javascript\" src=\"file.js\">" + "</script>"); //修改方法如下 document.write("<script type=\"text\javascript\" src=\"file.js\">" + "<\/script>");
-
[注意] 當網頁已經讀取完才執行 document.write(),則裡面的內容會完全覆蓋掉目前網頁
1 2 3
window.onload = function() { document.write("Jean Jin Jingle"); };
window.onload
表示網頁已載入完成,此時無論原本網頁有什麼內容,都會被 Jean Jin Jingle 覆蓋過去
DOM節點的修改與刪除
如何將新建好的DOM節點,置入到所指定的位置?
NODE.appendChild(childNode)
|
|
NODE.insertBefore(newNode, refNode)
將新節點 (newNode) 插入至指定的 refNode 節點的前面
NODE.replaceChild(newChildNode, oldChildNode)
將原本的 oldChildNode 替換成指定的 newChildNode
NODE.removeChild(childNode)
將指定的 childNode 子節點移除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<body> <ul id="myList"> <li>Item 01</li> <li>Item 02</li> <li>Item 03</li> </ul> </body> <script> //取得容器 let myList = document.getElementById('myList'); //取得"<li>Item 02</li>"的元素 let removeNode = document.querySelectorAll('li')[1]; //將myList下的removeNode節點移除 myList.removeChild(removeNode); //將myList裡面的HTML內容一口氣清空 myList.innerHTML = ''; </script>
DOM 節點的樣式
常見使用 JavaScript 修改 CSS 的方法有以下三種:
- 直接修改元素的 style 屬性
- 透過修改 className 屬性或 classList 提供的 api 修改元素的 class 屬性
- 利用 JavaScript 直接寫入 CSS 樣式
(1) 修改元素 style 屬性
屬於修改行內樣式的類型
1 2 3 4 5 6 7
<body> <div class="box"></div> </body> <script> let box = document.querySelector('.box'); box.style.color = 'red'; </script>
這種寫法是透過 DOM api 修改元素行內樣式,優先級會高於多數的其他樣式寫法(除了
!important
)⭐注意,CSS屬性名稱
-
kebab-case 要改成駝峰式寫法,JavaScript的變數以及物件名稱不允許用破折號
1 2 3 4 5
// style.font-size Error ❌ box.style.font-size = '20px'; // camel case ✅ box.style.fontSize = '20px';
(2) 修改元素 class 屬性
修改元素style屬性(行內樣式)容易帶來不易維護/除錯的問題,基於關注點分離的原則,實務上還是會把預先定義的樣式統一在CSS的class內處理
⭐注意,因為
class
是JavaScript保留的關鍵字,所以是透過 className 操作
🥝page150🚧
用 JavaScript 直接寫入 CSS 樣式
BOM 與 window 物件
BOM(Browser Object Model 瀏覽器物件模型)
window 物件
與網址列相關: location 與 history
JavaScript @ browser (2nd)
事件機制原理
事件流程
事件冒泡
事件捕獲
事件註冊綁定
on-event處理器(HTML屬性)
on-event處理器(非HTML屬性)
事件監聽 EventTarget.addEventListener()
關於addEventListener的第三個參數
非侵入式 JavaScript
在頁面載入到瀏覽器中,才去相應地執行事件設定。
是在原有基礎增加行為層分離,做到關注點分離,避免在HTML標籤裡面夾一對onchange
、onclick
屬性來註冊 Javascript 事件。
|
|
網頁事件與生命週期
事件種類
網頁介面相關事件
-
load()事件: 網頁資源(CSS、JS、圖片)全數載入完畢後才觸發
-
unload()事件: 在離開頁面或重新整理時觸發
-
beforeunload()事件: 會跳出對話框詢問是否要離開目前頁面
-
error()事件: document或image載入錯誤時觸發
-
大多數事件註冊建議使用非侵入式JavaScript, 只有error事件適合以on-event handler寫法來處理
1
<img sroc="image.jpg" onerror="this.src='default.jpg'">
-
-
resize()事件: 瀏覽器
window
或指定元素element
尺寸變更時 -
fullscreenchange()事件: 使用
-
scroll
-
DOMContentLoaded()
滑鼠相關事件
鍵盤相關事件
表單相關事件
特殊事件
Composition Event(組成事件)
剪貼簿事件
自定義事件
隱藏在事件之中的秘密
註冊事件的方法addEventListener()
的三個參數
- 事件名稱
- 事件處理器 Event Handler
- 捕獲或冒泡的機制切換
隱藏在Handler中的"event"
阻擋預設行為event.preventDefault()
用來取消預設行為,但不會阻止事件向上傳遞(事件冒泡)
阻擋事件冒泡傳遞event.stopPropagation()
在事件中找回自己
事件指派(Event Delegation)
函式、物件、原型鍊(上)
再談函式與參數
一級函式(First class functions)
可以將函式存在變數、物件甚至是陣列之中
|
|
函式是一種物件,值也是物件
|
|
函式的參數
<函式名稱> <小括號(> 參數
> <小括號)>
ES6的箭頭函式
Arrow Function expression features:
- 韓式寫法更簡短
- this變數強制綁定
即使箭頭函式不需要參數時,前面的小括號也不能省略
|
|
只有一個參數時可省略前面的小括號
|
|
call()
與 apply()
- call():
- param1: this (可傳入null)
- params …: 呼叫函式的參數,以
,
相隔
- apply():
- param1: this
- param2: 呼叫函式的參數,用一個陣列包覆
JavaScript不會檢查代入的參數數量,所以如果沒有傳入制,那麼未指定的參數預設就會是undefined
arguments 物件
arguments代表實際傳入的參數。
即使函式定義只有兩個參數,還是可以透過 arguments 取得多餘的傳入參數。
-
雖然像是陣列,實際上只是帶有索引特性的物件,並且內建length屬性
-
沒有陣列才有的
.map()
、.filter()
方法 -
內建另外一個屬性
callee
,指的是目前執行的函式- 執行遞迴(在函式內呼叫本函式)可透過
arguments.callee()
達成
- 執行遞迴(在函式內呼叫本函式)可透過
-
可以透過
slice()
或者Array.from
(ES6) 將arguments轉成陣列1 2 3 4 5
const args = Array.prototype.slice.call(arugments); //or const args = [].slice.call(arguments); //or in ES6 const args = Array.from(arguments);
其餘參數(rest parameter)
...args
:
-
當函式的最後一個參數以…作為開頭來命名,會被視為一個陣列,並且將所有參數存入這個陣列中
-
可以使用 arguments 沒有的 reduce 方法,讓此 plus 函式更加簡短
1 2 3
const plus = (...args) => args.reduce((a, b) => a + b); plus(1,2); pluc(1,2,3,4);
以物件作為參數
將多個參數用一個物件包裝起來
|
|
參數的預設檢查
避免少傳遞的參數變成 undefined ,結果變成 NaN 的時候…
小花可以這樣做
|
|
比較嚴謹的寫法
|
|
更好的寫法 (after ES6) - 替參數指定預設值
|
|