# 第四次
###### tags: `課程`
:::spoiler TODOs
:::warning
#### TODOs
##### javascript
- [x] history
- [] interpret language (may bey too much)
- [] Chrome V8 engine
- [] Just In Time Compiler
- [ ] relatives: es6, commonjs, typescript, coffescript
- [x] Variable
- [x] Types
- [x] week typing language
- [x] var v.s. let
- [x] Functions
- [x] anonymous function
- [x] arrow function
- [ ] Object Orentied
- [ ] prototype
- [x] key:value
- [x] this keyword
- [x] export
- [ ] Concurrency
- [x] callback
- [ ] async
##### Others
###### Mongoose
- [ ] schema
- [ ] model
- [ ] document
###### Some express thing
- [ ] router
- [ ] app.js
- [ ] package.js
:::
:::
:::info
由於它內容實在是太多太深奧,我盡量講點我懂的東西,以及比較可能會讓人困惑的東西
:::
```
^ ^
( OwO)
|m |m
b b
```
# 奇怪的 JavaScript
## 歷史系! :fire:
### Browser
- 1995年 Netscape 的 Brendan Eich 設計了第一版的 "JavaScript"
- 1997年 Netscape 向 ECMA International歐洲國際標準組織提交 JavaScript,產生了初版的 ECMAScript 草案,自此 ECMAScript 成為標準規範
- 2003年
- Netscape 解散,並開放程式碼
- Miscrosoft 反壟斷法敗訴
- Apple 加入戰局,使用開源專案 "渲染引擎 Webkit" ,釋出 Safari
- 2004年 Mozilla 繼承 Netscape 程式碼釋出 Firefox
- 2008年 Google 釋出 Chrome,使用 Webkit 與自行研發的 "V8-engine"
- chrome 核心:Chromium 以開源專案的方式釋出
- 2012年 Chrome 與 IE 產生死亡交叉
- 2015年 Microsoft 發布 Edge
- 2018年 Microsoft 發布 Chromium 版 Edge
- 2021年 Microsoft 決定方棄 IE
- To Be Continue...
### require vs import
一種功能兩種寫法
https://github.com/seajs/seajs/issues/588
https://ithelp.ithome.com.tw/articles/10191478
### 居然!?
- 據說第一板的設計只花了 10 天
- 取做 "javascript" 的原因是因為想要蹭當時超人氣語言 Java 熱度
- `Node.js` 是使用 V8-engine 來執行 JavaScript 程式碼的
- V8 engine 是用 C++ 寫的
### 歷史影響
ECMA 只負責定規格,至於怎麼實做(引擎)則是開發者自己想辦法
> [相關文章](https://ithelp.ithome.com.tw/articles/10191345)
## 程式語言特性
> 難,可以不用太在意這一段
> 這段基本上可以跳過
### Interpreter language
- 不會直接變成執行檔,需要用一個 interpreter 解釋執行原程式碼
- 不會像 C 那樣要先變成一個執行檔再執行它
- 所以其實 JavaScript 是被另一個程式來模擬執行的
- firefox, chrome, safari, 等內部都有各自的 javascript engine
### Week typing
- variable 型態隨時都可以被改變
```javascript=
let a;
a = 1.0; // the typeof a is Number
a = 'OwO'; // the typeof a is String
```
:::success
Week typing 與 Strong typing 不是非黑及白的分類,而比較像是一種線性的分佈
e.g.
Week typing <--- `JavaScript`--`python`--`C` ---> Strong typing
:::
### JIT (Just In Time Compiler)
V8-engine 中有 Just In time Compiler,
當執行 JavaScript 程式時,若途中發現有一段程式碼不斷的被執行很多遍,便會啟動 JIT 多花一點的時間將這段程式碼用更優化的方式翻譯,並緩存起來以便下次使用。
基於這樣的 JIT 的機制導致 JavaScript 雖然是直譯語言但是仍然有不錯的執行效率。
### Garbege collection
用不到的 variable 會在一段時間後被刪掉
## Variable
### Declaration
總共有三種不同的宣告方法:`var`, `let`, `const`
#### Hoisting
```javascript=
console.log(a); // 可以正常使用,output: undefined
var a = 1;
```
```javascript=
console.log(a); // error: Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 1;
```
```javascript=
console.log(a); // error: Uncaught ReferenceErro: Cannot access 'a' before initialization
const a = 1;
```
`var` 這種宣告方是會有 _Hoisting_ 的現象,變數會像是被 “提前” 一樣,在被宣告的那一行之前就能使用。這是因為 Node.js 在執行 JavaScript code 時會有兩個階段:_Parsing_ 與 _Executing_
_Parsing_ 階段會掃過一遍確認有哪些 variable/function declaration (確認有 變數/函式 是存在的)
而 _Executing_ 時再確實執行他們
> 注:這邊的階段分的很隨意,實際上有更複雜的階段與細節,這裡不詳述,因為我也不會
```javascript=
// Paring
console.log(a);
var a = 1; // <- 找到 declaration
var a; // <- a 已經被宣告過,無視
console.log(a);
---------------------------------
// Executing
console.log(a); // a 還未初始化,值為:"undefined"
a = 1; // 把變數 a 中裝入 1
console.log(a); // 這就會印出 1 了
```
`let` 與 `const` **不會**有 _Hoisting_ 的現象,使用 `let` 和 `const` 宣告的變數會在執行才被宣告,因此重複宣告是會報錯的。
```javascript=
console.log(let_variable); // let_variable 未宣告,程式 爆 error, crush
let let_variable; // <- 不會在 Parse 階段被掃到
```
:::danger
:no_entry_sign:
不建議使用 `var`,因為他可能會導致程式便的很難 debug
譬如:
```javascript=
var myVariable = 10; // 你的程式碼
...
...
var myVariable = 11; // 別人後來更新的程式碼,變數名剛好也取做 `myVariable`
...
...
console.log(myVariable); // 你的程式碼
```
這樣程式仍然能運作,但是你負責的那一塊卻變的怪怪的了,然後你想破頭也不知道到底為什麼會這樣。
如果大家都使用 `let` 就可以避免這個問題了。因為會直接爆掉說那裡錯了。
:::
#### `const` : constant
`const` 也就是 constant。當你希望設一個不會改變的變數時就可以設成 `const`,避免有哪個小王八蛋(~~自己~~)想改變他。只要有人想改他程式就會直接原地爆破。
```javascript=
const pi = 3.141592653589793;
...
pi = 100; // TypeError: Assignment to constant variable.
```
#### 小結
- `var`:
- 會 Hoisting
- 可以重複宣告不會報錯
- ~~混沌邪惡~~
- `let`:
- 跟其他語言比較接近的使用方式
- ~~守序中立~~
- `const`:
- 常數
- ~~絕對中立~~
> 查看更多:
> - [MDN Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
> - [更詳細的](https://www.freecodecamp.org/news/javascript-execution-context-and-hoisting/)
### Scope
變數有他的使用範圍,過了使用範圍就無法使用它了。
這樣的設計是問了讓你可以不用整天去煩惱一堆人撞名的問題。
```javascript=
let x = 1;
while (true) {
let x = 2; // 這個二號 x 只存在於 whlie 迴圈內
console.log(x); // 2
break;
}
console.log(x); // 1, 這邊的 x 指的是一號 x
function foo() {
let x = 3; // 這個三號 x 也只存在於 foo() 內
}
function bar() {
x = 100; // 由於 bar() 內沒有 x,所以需要往外找,因此這個 x 是一號 x
}
```
變數 scope 基本上就是在一個 _Code Block_ 裡(可以當成兩個大括號內的程式碼區)
:::warning
#### 注意 :heavy_exclamation_mark:
`var` 在 Scope 上有個例外,`function` 可以把 `var` 分開來
但是 `var` 可以穿透 `while`, `for` 等程式區塊。
```javascript=
for (var x = 0; x < 10; x++) {
}
console.log(x); // x 可以透出來!
```
不過你如果不用 `var` 了話也不太會有這樣的問題就是了
:::
### Type
JavaScript 的 Type 可以分為兩種: _Primitive_ 與 _Object_
- Primitive type
- Number
- String
- Booleam
- Null
- Undefine
> pay attension to the `null` and `undefine`. it may make you program crush
- Object
- Function
- > 是的在 JavaScript 中 Function 也是一種變數型態!
- Array
- Number
- String
- Booleam
- Date
- ...
::: spoiler 奇異的小知識
:::success
#### 奇異的小知識 :open_book:
- 在 V8-engine 的實做(C++)中,一個 variable 事實上只有三種型態 `int`, `double`, `pointer`
其他型態是模擬出來的。
- Array 其實背後有分`int array`, `double array`, `object array`
- 在新增元素時,若目前的型態不支援便會轉型
:::
:::success
#### 更奇異的小知識
- `NaN`: Not a Number 是一種 Number
- 如果呼叫 `typeof null` 它會說是 `object'.
```javascript=
typeof NaN; // Number
typeof null; // object
```
> reference: [你懂 JavaScript 嗎?#4 型別(Types](https://cythilya.github.io/2018/10/11/types)

:::
在 JavaScript 中,一個變數的型態可以不斷的改變
```javascript=
let a; // undefine
a = 1; // number
a = 'aa'; // string
a = [1, 2, 'b']; // object (Array)
```
### primitive vs object
> primitive is immutable
primitive type 就是那些基礎型態的東西,而且他們是 immutable 的
注意: 你不能“修改” primitive 的值,但是可以改變 variable 中裝的 primitive 值
```javascript=
let a = 1;
b = a;
```
```graphviz
digraph {
node [shape="record"]
a [label="a|1"]
b [label="b |1"]
}
```
> object is kind of referencing or pointer
一個 Object 可以擁有自己的 method 與 attribute。
一個 variable 不會 “裝著” object 而是 reference 到 object (可以姑且當成是“指著”)
==這裡是重點!==
```javascript=
let v1 = [1, 2, 3];
let v2 = v1;
// v2 並沒有 copy v1,而是 reference 到跟 v1 同一個 object
v2[2] = 4;
console.log(v1); // 會變成 [1, 2, 4]
```
```graphviz
digraph {
node [shape="record"]
v1 [label="v1|<p> "]
v2 [label="v2|<p> "]
subgraph cluster_heap {
label="Heap"
data [label="[1, 2, 3]"]
}
v1:p -> data
v2:p -> data
}
```
:::info
#### 腦荊棘轉彎
==TODO: 有點問題==
猜猜看以下的 code 會發生什麼事情
```javascript=
function swap(x, y) {
let temp = x;
x = y;
x = temp;
}
let a = 1, b = 2;
swap(a, b);
let o1 = [1, 2];
let o2 = [2, 3];
swap(o1, o2);
```
:::spoiler 答案
```graphviz
digraph {
node[shape="record"]
a [label="a |<p> 1"]
b [label="b |<p> 2"]
subgraph cluster_swap {
label="function swap"
x [label="x | 1"]
y [label="y | 2"]
}
}
```
```graphviz
digraph {
label="一開始"
node[shape="record"]
o1 [label="o1 |<p>"]
o2 [label="o2 |<p>"]
subgraph cluster_swap {
label="function swap"
x [label="x |<p>"]
y [label="y |<p>"]
}
subgraph cluster_heap {
label="heap"
data1 [label="[1, 2]"]
data2 [label="[2, 3]"]
}
o1:p -> data1
o2:p -> data2
x:p -> data1
y:p -> data2
}
```
```graphviz
digraph {
label="after some operation in function"
node[shape="record"]
o1 [label="o1 |<p>"]
o2 [label="o2 |<p>"]
subgraph cluster_swap {
label="function swap"
x [label="x |<p>"]
y [label="y |<p>"]
}
subgraph cluster_heap {
label="heap"
data1 [label="[1, 2]"]
data2 [label="[2, 3]"]
}
o1:p -> data1
o2:p -> data2
x:p -> data2
y:p -> data1
}
```
:::
:::
:::warning
#### 其他:
如果用
```javascript=
let a = new Number();
```
的寫法妳會得到一個 object 裡面裝著 number。他跟 primitive 的 number 是不太一樣的
:::
</br>
### Very Very Strange Comparison

在使用 `==` 時,兩邊的值會被轉型同一種型態後在進行比較
而 `===` 才會比較兩者的 type
- 非嚴格比較:`==`, `!=`
- 嚴格比較:`===`, `!==`
:::danger
除非你要做奇怪的事情,不然盡量用 `===` !
:::
> [`==` 的對照表](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Equality_comparisons_and_sameness)
## Objects
> [w3c school](https://www.w3schools.com/js/js_objects.asp)
當我們寫程式時,有時會想要操作一些“物件”。這時我們就可以使用 object 的概念。
:::info
info:
在不同的地方在討論 object 時會出現一些名詞像是:
_attribute_, _property_, _class member_
其實他們指的概念都差不多。
javascript 中 通常稱呼為 _property_
:::
```javascript=
// 可以單純當成一個資集合來操作
let car = {
// object 內容可以當成很多對的 key:value
color: 'Red', // color 就是 car 的一個 property
weight: 100,
}
car.color = 'Blue';
car.speed = 48763; // javascript 允許直接增加 property
```
### `this`
在 object method 中用來指稱自己的 keyword
```javascript=
let car = {
color: 'Red',
weight: 100,
beep: function() {
console.log(this.color); // 此處的 this 即為呼叫他的人:car
}
}
car.beep(); // 執行 beep method
```
> 
> 其實它還有其他更複雜的細節,好奇了話可以看這篇文章
> [淺談 JavaScript 頭號難題 this](https://blog.techbridge.cc/2019/02/23/javascript-this/)
### Prototype
> 難,可以不用太在意
JavaScript 中沒有像 Java 那樣的 `class` 寫法。取而代之的則是
Prototype 與 object 系統。
> [prototype chain](https://github.com/aszx87410/blog/issues/18)
## function
你可以宣告一段可以重複使用的程式碼段!
```javascript=
// 注意: javascript function 不會在意你到底放了什麼東西進來
// 因此它得實際行為可能會跟你想得不一樣!
function add(a, b) {
return a + b;
}
let c = add(1, 2); // 3
let d = add('a', 1) // 'a1'
let e = add(add(1, 2), 'a') // '3a'
```
### anonymous function
沒有名子的 function
```javascript=
// 將沒有名子的 function 存到 foo 裡面 (foo 指向它)
let foo = function(a, b) {
console.log(a + b);
}
foo(1, 2); // 3
// 原地執行
(function () {
console.log(a + b);
})(1, 2);
```
### arrow function
無名 function 的簡化寫法
```javascript=
let foo = (a, b) => {
console.log(a + b);
}
foo(1, 2); // 3
```
> arrow function 唯一的差別在於 `this` 的判定方式,細節可以去上面 this 的文章
> 難,可以不用在意這個小區別
### call back
既然我們可以把 function 裝進 variable 裡,那我們也可以把 function 作為另一個 function 的 input
```javascript=
function executeB(a, b) {
b(a);
}
function b1(a) {
console.log(a + 1);
}
executeB(1, b1); // 2
executeB(1, (a)=> {
console.log(a + 1);
}); // 2
```
為什麼要這樣寫?
因為在 JavaScript 裡常常會有想要某個 function 在特定的時候被觸發,像是:
server 接到 request 的時候,browser 的使用者點擊某個按鈕的時候。
```javascript=
let handler = (req, res) {
...
}
router.get('/hello', handler); // express 在接到對 'hello' 的request 時,就會再去執行 handler
// router.get('url', callback);
// router.get('/hello', (req, res) => {
// res.send(req.body.msg);
// })
```
## Promise
> 跳過ㄇ....
為了解決 callback hell,為了 Async 的和平
可愛又迷人的 Promise
then !
catch !
finally !
## Concurrency
Pain peko
> [講的非常非常清楚明瞭的影片](https://www.youtube.com/watch?v=8aGhZQkoFbQ)
> [一篇文章](https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5)
## Module
由於一開始 js 並不支援 Module 的使用,於是民間便自幹了一套 Module 系統。
稱作: common.js
而後過了一段時間後,EJS 才正式的發表了 `import` 的使用方法。
因此 JavaScript 中有兩種主流的 Module 使用方式
> [相關文章](https://ithelp.ithome.com.tw/articles/10191478)
```javascript=
// myModule.js
function add(a, b) {
return a + b;
}
// module.exports 就是到時候 require 時會回傳的東西
module.exports = add;
```
```javascript=
// main.js
const addFunction = require('myModule');
console.log(addFunction(1, 2)); // 3
```
> 另外的 `export`/`import 語法我就不再這邊介紹了`
## Helpful links
- [wiki](https://zh.wikipedia.org/zh-tw/JavaScript)
- [w3cschool](https://www.w3schools.com/js/default.asp)
- [es6 優質大文章](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/)
- [How javasciprt work: part1](https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf)
- [How javascript work: part2](https://blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e)
- [youtube: 關於v8機ㄓ](https://www.youtube.com/watch?v=UJPdhx5zTaw)
- [GeekofGeeks: variable](https://www.w3schools.com/js/js_let.asp)
- [MDN Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
- [高難度 Hoisting](https://github.com/aszx87410/blog/issues/34)
- [JavaScript comparison](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Equality_comparisons_and_sameness)
- [解釋 javascript 執行流程](https://www.youtube.com/watch?v=8aGhZQkoFbQ)
- [concurrency 講的非常非常清楚明瞭的影片](https://www.youtube.com/watch?v=8aGhZQkoFbQ)
- [concurrency一篇文章](https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5)
- [prototype chain](https://github.com/aszx87410/blog/issues/18)