JavaScript review
Entry
何謂 JavaScript
JavaScript 是一種直譯的程式語言,原本是設計給瀏覽器使用,現在已被應用到不同的環境,含 Server 也有使用到
何謂 ECMAScript
定義 JavaScript 的規格
== 和 === 的差異
== 比較値, === 比較値和資料型態
promise 是什麼
一種 JavaScript 的 object, 一般用於處理非同步的程序
Strict mode(嚴格模式) JavaScript
JS 引擎會用嚴格的標準來讀你的 code,避免你寫出不穩定或不夠嚴謹的 code, 讓你寫出的 Javascript 更安全
null 和 undefined 的差別
undefined : 變數宣告但為賦值
null : 變數設定代表無值
AJAX
Asynchronous JavaScript and XML,AJAX向伺服器傳送要求取回必須的資料,並在客戶端採用JavaScript處理來自伺服器的回應.
synchronous(同步) 與 asynchronous(非同步的) 差異
同步為執行完成目前的程序再執行後面的程序,非同步則不等待執行完成繼續往後執行,如執行 AJAX 就要使用非同步,不然就有可能出現網頁卡住的現象
var, let 和 const 的差別
- var 是 function scope, let 和 const 是 block scope
- var,let 設定後可更改, const 不可更改
DOM(文件物件模型) 是什麼
Document Object Model,提供了一個文件(樹)的結構化表示法,並定義讓程式可以存取並改變文件架構、風格和內容的方法。
資料型別 Primitiv(原始) and Object(物件)
JavaScript 的資料型別有 Primitiv value(原始值) 和 Object(物件) 兩類
Primitiv value :
- Boolean type
- Null type
- Undefined type
- Number type
- BigInt type
- String type
- Symbol type
Object :
- Function
- Array
- Date
- ….
1 | // Primitive |
window.onload 和 $(document).ready()
- window.onload 會等網頁的全部內容,包括圖片,CSS及<iframe>等外部內容載入後才會觸發
1
2
3
4
5
6
7
8window.onload = function() {
func1();
func2();
....
}
// 若只需要執行單一 function
window.onload=Func; - $(document).ready()在Document Object Model (DOM) 載入後就會觸發,所以順序上$(document).ready()會比window.onload先執行。
1
2
3$(document).ready(() =>{
....
}
Middle
closure(閉包)
closure(閉包) 是一個 function 在另一個 function 的內部, 內部的 function 有 access function scope 的資料,雖然外部function 已 return,但還可以 aeecss 到 function 的資料
1
2
3
4
5
6
7
8
9
10
11
12function test() {
var a = 10
function inner() {
a++
console.log(a)
}
return inner
}
var func = test()
func() // 11
func() // 12
func() // 13應用 #1 - 複雜計算自動記憶不用重算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function complex(num) {
console.log('calculate')
return num*num*num
}
function cache(func) {
var ans = {}
return function(num) {
if (ans[num]) {
return ans[num]
}
ans[num] = func(num)
return ans[num]
}
}
console.log(complex(20)) // calculate 8000
console.log(complex(20)) // calculate 8000
console.log(complex(20)) // calculate 8000
const cacheComplex = cache(complex)
console.log(cacheComplex(20)) // calculate 8000
console.log(cacheComplex(20)) // 8000
console.log(cacheComplex(20)) // 8000應用 #2 - 隱藏資訊
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function createWallet(init) {
var money = init
return {
add: function(num) {
money += num
},
sub: function(num) {
money -= num
},
getMoney: function() {
return money
},
}
}
var myWallet = createWallet(99)
myWallet.add(1)
console.log(myWallet.getMoney()) // 100
myWallet.sub(20)
console.log(myWallet.getMoney()) // 80
函數原型內建函式 call, apply, and bind 的差別
call,apply 立即執行, bind 產生一個新函數提供之後使用(可更改 this 值)
call 的參數為個別傳入, apply 為 array 傳入
this 用不到可填入 null
1
2
3
4
5
6
7
8
9
10
function test(a, b, c) {
console.log(this)
console.log(a, b, c)
}
test(1, 2, 3) // undefined 1 2 3
test.call(123, 1, 2, 3) // 123 1 2 3
test.apply(123, [1, 2, 3]) // 123 1 2 3
var testBind = test.bind(123, 9 , 7)
testBind(99) // 123 9 7 99應用 #1 - apply 填入 this
1
2
3
4
5
6
7
8
9
10
11
12// apply
function log() {
console.log(this)
}
var a = {a:1, log:log }
var b = {a:2, log:log }
log() // undefined
a.log() // { a: 1, log: [Function: log] }
b.log() // { a: 2, log: [Function: log] }
b.log.apply(a) // 代入 a 為 this -> { a: 1, log: [Function: log] }應用 #2 - apply 參數轉為 array
1
2
3console.log(Math.min(1, 2, 3, 4)); // 1
const arr = [1,2,3,4];
console.log( Math.min.apply(null,arr)); // 1
Event Loop(事件循環)
JavaScript 的 Call stack 是擺放待執行的程序,JavaScript 對於不能馬上執行的動作,會呼叫對應的Wep Api(如setTimeout, AJAX …), 當 Web API 執行完後,會被堆放到callback queue,當 Call stack 已無待執行的程序,會順序從 callback queue 抓取程序到 Call stack 執行,順序從 callback queue 抓取程序到 Call stack 執行的流程及稱為 Event Loop
currying(柯里化)function
currying function 指的是將多參數函數轉為順序接收單一參數的函數
可簡化程式及提高程式的重用性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// discount function
function discount(price, discount) {
return price * discount
}
// 10% discount
console.log(discount(500,0.1)); // 50
console.log(discount(1000,0.1)); // 100
console.log(discount(2000,0.1)); // 200
// 20% discount
console.log(discount(2000,0.2)); // 400
// discount currying function
function discountCurrying(discount) {
return (price) => {
return price * discount;
}
}
const tenPercentDiscouint = discountCurrying(0.1)
const twentyPercentDiscouint = discountCurrying(0.2)
// 10% discount by currying function
console.log(tenPercentDiscouint(500)); // 50
console.log(tenPercentDiscouint(1000)); // 100
console.log(tenPercentDiscouint(2000)); // 200
// 20% discount by currying function
console.log(twentyPercentDiscouint(2000)); // 400General(通用) Currying Function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// General Currying Function
function curry(fn, ...args) {
return (..._arg) => {
return fn(...args, ..._arg);
}
}
function multiply(a, b, c) {
return a * b * c;
}
// multiply currying function
const multiplyBase2 = curry(multiply,2);
console.log(multiplyBase2(4,6)); // 48
function discount(price, discount) {
return price * discount
}
// 10% discount by currying function
const tenPercentDiscouint = curry(discount,0.1);
console.log(tenPercentDiscouint(500)); // 50
Constructor(建構) Function
- Constructor Function 可建立包含不同屬性(properties)的物件(object)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.eat = function () {
console.log(`${this.name} is eating.`)
}
Person.prototype.sleep = function () {
console.log(`${this.name} is sleeping.`)
}
Person.prototype.walk =function () {
console.log(`${this.name} is walking.`)
}
let Bob = new Person("Bob", 23);
let Bill = new Person("Bill", 40);
JavaScript prototype (原型)
- prototype 是 JavaScript function 的一個 屬性
- prototype 內有一個屬性 constructor 會指到原函數,也可利用 constructor 產生新的物件,新產生的物件可以利用__proto__指回原函數的內部函數
1 | function Person(name, age) { |
JavaScript prototype chain(原型鏈)
prototype chain 是 JavaScript 的 繼承機制
Object prototype : let apple = {} 與 let apple = new Object() 相同
1 | let orange = {} |
prototype chain : Function prototype + Object prototype
prototype chain : Array + Object prototype
prototype chain for all
Memoization
Memoization是一種優化技術,透過儲存曾計算的的結果,來增加應用程序的執行
一般費式數列遞迴計算(傳回第幾個費式樹列直)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48function fibonacci(n) {
console.log("count:", n);
if (n <= 1) {
return 1
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(` fibonacci${0} -->`, fibonacci(0));
console.log(` fibonacci${1} -->`, fibonacci(1));
console.log(` fibonacci${2} -->`, fibonacci(2));
console.log(` fibonacci${3} -->`, fibonacci(3));
console.log(` fibonacci${5} -->`, fibonacci(5));
// result ----
// >node fibonacci.js
// count: 0
// fibonacci0 --> 1
// count: 1
// fibonacci1 --> 1
// count: 2
// count: 1
// count: 0
// fibonacci2 --> 2
// count: 3
// count: 2
// count: 1
// count: 0
// count: 1
// fibonacci3 --> 3
// count: 5
// count: 4
// count: 3
// count: 2
// count: 1
// count: 0
// count: 1
// count: 2
// count: 1
// count: 0
// count: 3
// count: 2
// count: 1
// count: 0
// count: 1
// fibonacci5 --> 8Memoization費式數列(傳回第幾個費式樹列直)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39function memolizedFibonacci(n) {
let memo = {};
function fibonacci(n) {
if (memo[n]) {
return memo[n];
}
console.log("count : ",n);
if (n <= 1) {
return memo[n] = 1;
}
return memo[n] = fibonacci( n-1) + fibonacci(n-2);
}
return fibonacci;
}
let countFibonacci = memolizedFibonacci();
console.log(` fibonacci${0} -->`, countFibonacci(0));
console.log(` fibonacci${1} -->`, countFibonacci(1));
console.log(` fibonacci${2} -->`, countFibonacci(2));
console.log(` fibonacci${3} -->`, countFibonacci(3));
console.log(` fibonacci${5} -->`, countFibonacci(5));
// result ----
// >node fibonacci2.js
// count : 0
// fibonacci0 --> 1
// count : 1
// fibonacci1 --> 1
// count : 2
// fibonacci2 --> 2
// count : 3
// fibonacci3 --> 3
// count : 5
// count : 4
// fibonacci5 --> 8
Higher-order function
- 接收函式做為引數的函式(callback function) 或 回傳結果為函式的函式
- map, filter 和 reduce 即為內建的Higher-order function(傳回函數)
Event delegation(事件代理,事件委派)
- Event listen 放在父元素,而非個別的元素,如此可精簡程式及處理動態產生的元素
事件傳遞機制:捕獲與冒泡
- DOM 事件傳遞機制分成 3 階段:
- Capturing Phase 捕獲階段
- Target Phase 傳遞到元素本身
- ubbling Phase 冒泡階段
- 事件傳遞的兩個原則
- 先捕獲,再冒泡
- 當事件傳到 target 本身,沒有分捕獲跟冒泡
- 當使用 event.stopPropagation(),事件傳遞就會停在設置的地方
- 若在捕獲階段:阻止事件往下傳遞
- 若在冒泡階段:阻止事件向上傳遞
- 如果要讓同一層的事件也要停止,就用 stopImmediatePropagation()
圖片來自 W3C
preventDefault 與 stopPropagation 的差異
- preventDefault() 停止元素預設事件發生,如果只是要預防 <a href=”#”> 回到頁首,可加上這個函數
- stopPropagation() 停止作用的元素冒泡
JavaScript asynchronous(非同步) operation 處理方式
Callback : 藉由參數(argument)傳入一個函式,以便完成某件程序後執行必要的程式
Promise :
promise 為 ES6 增加的 object(物件)
他有三種狀態,pending(初始狀態)
fulfilled(事件完成)
rejected(事件失敗)狀態的改變只有兩種可能
從 pending 變成 fulfilled
從 pending 變成 rejected一但狀態改變就會固定,永遠不會再改變狀態.
async/await : ES2017(ES8) 增加的語法, 使非同步的程式看起來像是同步的程式
recursion(遞迴)
- 透過函式重複呼叫自己最終得到計算結果的一種方法
- 這是一個常用處理排序或遍歷(traversing)的方法
Hoisting (提升)
- var 宣告提升,但賦值不會提升
- let, const 有提升,但賦值前不能使用(所以外部宣告的變數不能使用)
- TDZ (Temporal Dead Zone)暫時性死區: let、const 在設定值前不能使用
- function 也會提升,所以可以將 function 寫在呼叫之後
1 | // var 宣告提升,但賦值不會提升 |
JavaScript 的繼承
prototype 範例
1 | // inheritance2.js |
class 範例
1 | // inheritance.js |
Fetch API
fetch()是 XMLHttpRequest 的升级版,提供了一個能獲取包含跨網路資源在的資源介面。它有點像我們所熟悉的 XMLHttpRequest ,但這個新的 API 提供了更強更彈性的功能。
Logical Operator vs Nullish Coalescing Operator
Logical Operator:當值為 undefined, null, false 或 0 則傳回右邊的值
1
2
3
4console.log(false || 'Hello'); //Returns Hello
console.log(undefined || 'Hello'); //Returns Hello
console.log(null || 'Hello'); //Returns Hello
console.log(0 || 'Hello'); //Returns HelloNullish Coalescing Operator::當值為 undefined 或 null 則傳回右邊的值
1
2
3
4console.log(false ?? 'Hello'); //Returns false
console.log(undefined ?? 'Hello'); //Returns Hello
console.log(null ?? 'Hello'); //Returns Hello
console.log(0 ?? 'Hello'); //Returns 0
參考資料
+ [Fetch API 教程](https://www.ruanyifeng.com/blog/2020/12/fetch-tutorial.html)