# [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 被呼叫的時候才執行