# [JS101] 用 JavaScript 一步步打造程式基礎
###### tags:`JavaScript 觀念`
> 待解之謎: `;`甚麼時候要放,甚麼時候不用放
> 爽就好,但是要統一
nodejs, 瀏覽器 都是 JS 的 runtime (= 執行環境)
`console.log(123)`會回傳undefined
`node file` 執行檔案
## || 與 && 的短路性質
|| 要找 true
&& 要找 false
## 左左右右:位移運算子
左左 << 1 二進位往左移一位
```
10 << 1 //20
// 二進位:1010 => 10100
// 相當於 *2^1
1 << 10 //1024
//二進位:1 => 10000000000
// 相當於 *2^10
```
右右 >> 1 二進位往右移一位
```
1024 >> 10 //1
// 二進位:10000000000 => 1
// 相當於 除以2^10
5 >> 1 //2
// 二進位:101 => 10
// 相當於 除以2^1
// 往右移如果不能整除的話會是無條件捨去
```
這兩個跟四則運算的乘法和除法有相同效果,理論上,這個方法的效能會比較好
## 位元運算的 and、or、xor 與 not
邏輯運算和位元運算是不一樣的運作方法,不要搞混。
例如:邏輯運算的 `&&` 是判斷 true / false,位元運算的`&`是對二進位做處理。
二進位的`1`,實際上是表示`00000(31)1`,不要只看到表面
* or `|`: 位元有 1 的話回傳 1,沒有則 0
* xor `^`: ~~做完 or 之後 not?~~,兩個位元一樣的話回傳 0,不一樣的話回傳 1
> `^` 在 JS **不是**表示乘以次方數
* not `~`: 把二進位轉換成十進位時,記得要考慮到 JS 用 32 bits 存放整數
### 比較一下邏輯運算 VS 位元運算
| 種類 | 邏輯運算 | 位元運算 |
| -------- | -------- | -------- |
| and |`&&` | `&` |
| or | `||` | `|` |
| not | `!` | `~` |
### 一些巧妙的用法
* 用 A and 0 來做位元的遮罩,遮罩的意思是把 A 的二進位位元轉換成 0
* 用 and 來判斷奇數或偶數
> 這個性質配合二進位的性質,效能上會比較好嗎
## 變數宣告與 undefined
用 `=` 賦值:把右邊的值用左邊代稱
undefined:有宣告變數但還沒給值
## 加加
`a++`, `a = a + 1` 是一樣的意思
`a++` not equal `++a`,前者是後加,後者是先加
## 變數的各種型態
可以去我之前做的 [JS筆記](https://github.com/chachachater/chachachater.github.io/tree/master/JS%E7%AD%86%E8%A8%98),有詳細的解釋
## 物件(Object)
array 可以放不同 type ,但一般不會這樣做,如果要達到放不同 type 的話,一般會使用 Object{ }。
> Object 裡面的 key-value 要記得放 `,`來分隔,常常忘記這點
### 呼叫
peter.name
peter['name']
## == 與 ===
差別在於會不會檢查 type,永遠都用 `===`才不會出現神奇結果
## 從 Object 的等號真正的理解變數
宣告 Object 的時候, Object 存放的是記憶體位址。
![Object1](https://i.imgur.com/i7r8v7p.png)
* 變動 Object 的 property 的話,記憶體位址**並不會**跟著改變
![Object2](https://i.imgur.com/xF0f4py.png)
* 把 Object 重新宣告的話,就會是全新的記憶體位址
![Object3](https://i.imgur.com/YaxMuxC.png)
## if/else statement
condition 如果有很多組的話,要用 `&&` 之類的邏輯運算連接起來
## switch case
記得要用 `break`來停止
如果 index 和 case condition 可以互相對應,其實也可以應 array 來解決,例如:
![例如](https://i.imgur.com/ppL05kW.png)
## 一、二、三:三元運算子(Ternary)
` condition ? A:B `
## 迴圈的前世:label 與 goto
JS 沒有的 syntax
```
var i = 1
label:
console.log(i)
i++
goto loop //去 label 下方第一行`
```
## 先做再說:do...while...
```javascript=
do {
something
if () {
break;
}
} while (true)
```
break : 跳出迴圈
continue : 跳到下一回圈
```javascript=
<script>
debugger
something
</script>
```
↑用 chrome 做 debugger
## while 迴圈 / for 迴圈
## 函式結構
* 函式也可以回傳 object,但要注意格式:
```javascript=
function abc (x) {
return {
answer: x*2
}
}
// 下面是錯的
function abc (x) {
return
{
answer: x*2
}
}
```
* 函式名稱、 argument名稱都要取得有意義
* 要隨時記得函數的 argument 只是一個代稱,以下面範例來說, argument transformFunction 指的是 test()
```javascript=
function transform (x, transformFunction) {
return transformFunction(x)
}
function test(x) {
return x*2
}
console.log(
transform(10, test)
)
```
### parameter 參數
宣告 functionion (a, b)的 `( )`內的 a 和 b是參數
### argument 引數
* 使用 function (1, 2)的 1, 2 就是引數
* JS 可以用 arguments[0]來查看引數
* arguments 實際上是一個 object,他長得很像 array,也有一些 array 的功能
```
obj {
0:'a',
1:'b'
}
obj[0] //a
但這情況不是通用的,第一是 obj.0 is invalid,第二是只適用在 obj key 剛好也是 index 形式的時候
```
### return 不 return,有差嗎?
* 函式沒有 return 的話預設是 return undefined
* return 也可以先做判斷再回傳,例如:
```javascript=
function (x) {
return x > 0
}
```
## Number 類型的內建函式
轉型成數字
```
var a = '20'
Number(a)
parseInt(a)
parseFloat(a)
```
數字轉字串的話 `console.log(20+"")`
最大值`.MAX_VALUE`
Math 系列
```
Math.cell()
Math.floor()
Math.sqrt()
Math.power()
Math.random 產生0-1(不包含1)的隨機數字
```
## String 類型的內建函式
把 char 轉換成 ASCII:`.charCodeAt(//string index)`
把 ASCII 轉換成 char:`String.fromCharCode()`
找出特定字串::
```
var inde = ....indexOf("bird")
if inde >=0 則表示存在
```
* 取代`.replace()`, 分割字串回傳 arr`.split()`, 去掉惱人的首尾空格`.trim()`
* `string.repeat(n)` 重複字串 n 次,然後回傳新的字串
* `str.slice(start, end)` 從 start-end切割字串
* `str.padEnd` 往str 末端塞字串
* `str.EndsWith(str)` 判斷字串結尾是不是 str
## Array 類型的內建函式
* 把 array 的每一個值用 ','來分開,然後變成一個 字串`.join(',')`
* 把 array 的每一個值用一個 function 來做處理,然後回傳給 array`.map(functionName)`
* 把 array 的每一個值用一個 function 來做處理,回傳 true 給 array`.filter(functionName)`
* 把 array 的某些 index (連續)取出來`.slice()`
* `.splice()` 對 arr 的 element 做取代, 移除, 新增
* 大小排列`.sort([compareFunction(a, b)])`,[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
function return 負數 =>a, b不互換
function return 負數 =>a, b unchanged
function return 正數 =>a, b 互換成ba
* `arr.map(callbackFn)`,callbackFn 會被每一個 arr element 使用,然後回傳**新的陣列**
> callbackFn : Function that is called for every element of arr.
* `arr.indexOf(4)`,從頭找出 arr 裡面的 4 這個值所在的 index.
* `arr.lastIndexOf(4)`,從末端找出 arr 裡面的 4 這個值所在的 index.
* `arr.fill(arr, str)` 把 arr 的 element 改成 "str"
* `string.endsWith(str, searchStr)` 判斷 str 是不是以 searchStr 結尾
* `arr.fileter(arr, callback)`
* `arr.reverse()` 反轉 arr
## 容易搞錯的三胞胎
* str.slice() //取出 str 的連續一部分然後回傳新字串
* arr.splice() //對 arr 的 element 做取代, 移除, 新增
* str.split() //把 str 根據某個符號做分割,並放到 arr,然後回傳 arr
### 延伸
* `arr.join` 會把 arr 合併成字串
* `str.split("")` 會把 str 分割成 arr
## 「回傳」與「印出」的差異
正常的 pattern 長這樣↓,function 一般用 return 而不是 console.log
![pattern](https://i.imgur.com/VnSAJqZ.png)
## Immutable 觀念
**一些內建的 FUNCTION 不一定會回傳使用者的想法,使用之前要先查文件確認**
immutable value
> All types except objects define immutable values [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#primitive_values)
```
var a = "hi" //a:"hi" 0x11
a = a.toUpperCase() //a:"HI" 0x23
```
變數 a 的記憶體位址變成 0x23,但 0x11 這個記憶體還是依樣存放著 "hi" ,它沒有從記憶體裡面消失(= immutable)
## 補充閱讀資料 ~~(還沒讀)~~
1. [Stack 與 Heap 有何差別](https://medium.com/@yauhsienhuang/stack-%E8%88%87-heap-%E6%9C%89%E4%BD%95%E5%B7%AE%E5%88%A5-acdcc11263a0)
1. [Call Stack 呼叫堆疊](https://ithelp.ithome.com.tw/articles/10206190)
1. [stack vs heap:執行時期儲存兩大要角](https://antrash.pixnet.net/blog/post/70456505-stack-vs-heap)
1. [深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?](https://blog.techbridge.cc/2018/06/23/javascript-call-by-value-or-reference/)
### Stack 與 Heap 有何差別
stack 是一種後進先出的記憶體存放方式,呼叫 fn 的時候相關的參數和值也放在這邊
heap 是一大塊空空如也的記憶體,用來存放程式中的所有資料
### Call Stack 呼叫堆疊
JavaScript的執行環境分為全域執行環境與區域執行環境。
全域只會執行一次,區域(stack、heap)則會等到 fn 被呼叫的時候才執行