###### tags: `Javascript` `運算子` `短路性質` `可變與不可變` `基礎語法` # JavaScript 101 ─ 重點整理 ## 在瀏覽器內執行 JS 1. 新建 index.html 檔案。 2. vim 編輯內容。 ```htmlmixed= <script>  console.log(‘hello world’); </script> ``` 3. 回到 cmder ,直接打開 index.html,會直接瀏覽器打開。 ## 在 CMI 編輯 JS 檔案 1. 新建 index.js 檔案 2. vim 編輯內容。 3. 編輯:`console.log(‘hello world’);` 4. 回到 cmder ,輸入 node index.js,即可看到內容出現在 CMI 上。 ## 在 CMI 直接執行 JS 1. 在 CMI 輸入 `node`,下一列會出現大於符號。 2. 在大於符號旁輸入任何語法和運算,即可執行 JS。 3. 若想要離開,可按 `^C`,或者是輸入 `.exit` 即可離開跳出。 ## 運算子 1. 等於`===` 2. 不等於 `!==` 3. and `&&` 4. or `||` 5. not `!` 範例: ```javascript= let mood = 'sleepy'; let tirednessLevel = 6; if(mood === 'sleepy' || tirednessLevel > 8){    // TRUE console.log('time to sleep'); //所以顯示time to sleep } else { console.log('not bed time yet'); } ``` ## 短路特性(邏輯運算) 1. true || false,回傳前值(因為到了第一個值就發現是 true)。所以像是 200 || 20,會回傳200。因為到了第一個就發現是true,就會馬上回傳第一個值。 2. false || true 回傳後值,因為需要看到最後。所以 0 || 22 回傳22。 3. true && true 、true && false 都是回傳後值。因為要看到最後一個才會知道是 true 還是 false。所以像是 32 && 50 會回傳 50,22 && 0 會回傳 0。 4. false && true 會回傳前值,因為第一個就發現是 false,就不需要接著看了。所以 0 && 22 會回傳 0。 ## 二進位換算 1. 運算方式:個位數是二的零次方乘以個位數的數字,十位數是二的一次方承以十位數的數字,百位數是二的二次方承以百位數的數字,以此類推。 2. 舉例:101100 = 2^5 * 1 + 2^4 * 0 + 2^3 *1 + 2^2 *1 +2^1 *0 = 2^5 + 2^3 + 2^2 = 32 + 8 + 4 = 44 ## 位元運算 1. `<<`:將位元往左移一位,可將其看成乘以 2 的幾次方。舉例來說:10 << 2 = 10 * 2^2 = 40、3 << 4 = 3 * 2^4 = 48。 2. `>>`:將位元往右移一位,可將其看成除以 2 的幾次方。若不能整除會直接捨去。舉例來說:1024 >> 2 = 1024 / 2^2 = 256、57 >> 4 = 57 / 2^4 = 3 (直接捨去) 3. `&`(and): 1. 先將十進位的數字換算成是二進位的數字。10 & 15 = 1010 & 1111。 2. 直立式運算。0 and 1 會變成0(0 是 false 1 是 true)、1 and 1 會變成 1,以此類推,1010 and 1111 = 1010。 3. 將結果還原成十進位。1010就是10。 4. 答案:10 & 15 = 10。(詳細解法如下圖) ![](https://i.imgur.com/vqYhC7j.jpg) 4. ` |`(or): 1. 先將十進位的數字換算成是二進位的數字。10 | 15 = 1010 & 1111。 2. 直立式運算。0 or 1 會變成1(0 是 false 1 是 true)、1 or 1 會變成 1,以此類推,1010 or 1111 = 1111。 3. 將結果還原成十進位。1111 就是 15。 4. 答案:10 | 15 = 15。(詳細解法如下圖) ![](https://i.imgur.com/coVNAOa.jpg) 5. `^`(xor)(發音 exclusive or): 1. 先將十進位的數字換算成是二進位的數字。10 ^ 15 = 1010 ^ 1111。 2. 直立式運算。一樣的數字就會變成 0,不一樣的就會變成 1。1010 ^ 1111 = 0101。 3. 將結果還原成十進位。0101 就是 5。 4. 答案:10 ^ 15 = 5。(詳細解法如下圖) ![](https://i.imgur.com/z9aFWLj.jpg) 6. `~`(not): 1. 先將十進位的數字換算成是二進位的數字。 2. 1 變成 0、0 變成 1。 3. ~15 = -16 ;~ 27 = -28 ## 變數 Variable 1. 名詞解釋 * undefined:有宣告,但沒有賦予值。例如:var apple = * not defined:連宣告都沒有。 2. 命名方式 * 不可以用數字開頭(會出現 unexpected number):例如:var 123apple = 22。 * 不可以用程式語言本身的功能字命名:例如:var var = 22 * 命名有底線式跟駝峰式,基本上都以駝峰式為主。 底線式如 var thank_you = “Thanks”。 駝峰式如 var ThankYou = “Thanks”。 3. a++ 與 ++a * 兩者的共同點:a++ 和 ++a 就是 a = a +1 也等於 a += 1。 * 兩者的差別: a++ 會待整個列執行完後,才會再執行 a++。 ```javascript= var a = 0; console.log(a++ && 30) //顯示 0 ``` 因為它會看成 console.log ( a && 30 ),這列執行完,再看 a++。 ++a 則是正常執行。 ```javascript= var a = 0; console.log(++a && 30) //顯示 30 ``` 因為此時就是單純執行 console.log( ++a && 30 )。 ## = 與 == 與 === 的意義及差別 1. =: 一個等號的意思是賦值(宣告)。 2. == 跟 === 皆判斷兩邊是否相等,但 === 會比 == 多比較兩邊的型態及多比較記憶體的位置。 ```javascript= console.log(0 == '0'); // true console.log(0 === '0'); // false,因為一邊是數字一邊是字串 ``` ### 字串 Object 中的等號 ```javascript= var obj = {a:1}; var obj2 = obj; ``` 以上的兩行程式碼當中的記憶體位置會如下圖所示。 ![](https://i.imgur.com/u4TZQHD.jpg) 第一行像是我將 { a:1 } 存在某個記憶體位置(0x01),而 obj 內存放在這個記憶體位置(0x01)。 而第二行 obj2 變數不會再新增一個記憶體,他會直接導向 obj 的記憶體位置(0x01)。 那如果我更改 obj.a 這個物件呢? ```javascript= var obj = {a:1}; var obj2 = obj; obj2.a = 2; console.log(obj === obj2) // true ``` 以上的程式碼當中的記憶體位置會如下圖所示。 ![](https://i.imgur.com/xC4IYGV.jpg) 我們在第三行更改了 obj2.a 的值,按照剛剛的邏輯,他會更改記憶體位置(0x01)的內容,所以這時結果仍然是 true。 那如果我們另外新增一個物件,而非更改既有的呢? ```javascript= var obj = {a:1}; var obj2 = obj; obj2.a = 2; obj2 = {b:1}; console.log(obj === obj2) // false ``` 以上程式碼的記憶體位置如下圖。 ![](https://i.imgur.com/9ZRRGkg.jpg) 此時就無法再更改記憶體位置(0x01)的內容了,因為這邊新增的是 {b:1},但在 0x01 裡面並沒有 b。所以這時後 obj2 就會另開一個記憶體位置(0x05),並在此放入 {b:1}。因此,結果才會是 false。 ## 可變(mutable)與不可變(immutable) ### 觀念 * 除了陣列跟物件是可變的外,其他都是不可變的(boolean, float, integer, string) * 重點是內容可不可變,而不是變數可不可變。 直接透過範例更了解可變與不可變的觀念。 ### 不可變(immutable)範例 ─ 字串string ```javascript= let fruit = 'apple'; fruit.split('') // 字串的的內容是不可變的,所以不可以在同一個記憶體位置內更改 fruit 的內容。 console.log(fruit); // apple ``` 若要更改字串需重新賦值,如下。 ```javascript= let fruit = 'apple'; fruit = fruit.split('') // 將透過空格給切開的 fruit 重新找個記憶體位置儲存,一樣貼了 fruit 的標籤 console.log(fruit); // ['a', 'p', 'p', 'l', 'e'] ``` ### 可變(mutable)的範例 ─ 陣列(Array) ```javascript= let fruit = ['apple', 'banana']; fruit.push('orange'); // 不需要另存記憶體,直接進行更改 console.log(fruit); // [ 'apple', 'banana', 'orange' ] ``` 那如果我這時候將改變後的陣列另存記憶體呢? ```javascript= let fruit = ['apple', 'banana']; fruit = fruit.push('orange'); console.log(fruit); // 3 // 這邊印出的是陣列的元素數(共 3 個) ``` 為什麼這邊印出來的是 3 呢? > 因為`.push()` 這個函式的回傳值是最新的陣列長度 所以當這時候我將這個函式的結果存到 fruit 裡的時候,就會將回傳值存進去,而這裡的回傳值是 3。 除此之外,要特別注意的是,某些陣列函式回傳值不是陣列,這時候就會需要另存記憶體。 ```javascript= let fruit = ['apple', 'banana', 'grape']; fruit = fruit.join('--'); //.join() 回傳值是 String,需另存 console.log(fruit); // apple--banana--grape // 印出的格式也是字串格式 ``` ## 條件句 ### If else #### 特性 * if 條件句裡會判斷是否為 TRUE,如果是的話會執行,不是的話就會跑到 else / else if。 * if 條件句內,數字不可為 0、字串不可是空的、不可以是未定義的變數、不可以是 null、不可以是 NaN(Not a Number)。 結構如下: ```javascript= if (條件一) { 若條件一符合,執行此語句 } else if (條件二) { 若條件二符合,執行此語句 } else if (條件三) { 若條件三符合,執行此語句 ... } else { 若都沒有符合的,執行此語句 } ``` 範例: ```javascript= function testNum(a) { if (a > 0) { return "positive"; } else if (a = 0) { return "It's zero"; } else { return "NOT positive" } } console.log(testNum(-5)); // "NOT positive" ``` ### ternary operator 三元運算子 > 將 IF … ELSE… 條件句縮寫 縮寫結構:`條件式 ? 對的話做這件事 : 不對的話做這件事;` ```javascript= let favoritePhrase = 'Love That!'; if (favoritePhrase === 'Love That!') { console.log('I love that!'); } else { console.log("I don't love that!"); } ``` 以上是普通條件句寫法,以下使用三元運算子。 ```javascript= favoritePhrase === 'Love That!' ? console.log('I love that!') : console.log("I don't love that!"); ``` ### Switch Case 除了一般的 `if`、 `else if`、`else` 外,也可以使用 Switch Case 來執行條件句。 ```javascript= let athleteFinalPosition = 'first place'; switch(athleteFinalPosition) { case 'first place': // 代替 if console.log('You get the gold medal!'); break; // 如果 run 成功,break 用來防止繼續 run 到下一個 case 'second place': console.log('You get the silver medal!'); break; default: // 如果以上都不符合,那就 run 這個。 = else console.log('No medal awarded.'); break; } ``` ## 陣列 Array ### 特性 * 屬於物件型別,所以其屬於可變的,其相關的內建函式有些會改變原陣列,有些不會,也不一定都會回傳值 * 儲存於變數時,實際儲存的是記憶體位置 * 陣列內部可以再放入陣列 ### 使用方式 存取性質相近(都是數字或是字串)、重複性高(可能有十幾個物件)。 ```javascript= var student_scores = []; student_scores[0] = 87; student_scores[1] = 27; student_scores[2] = 57; console.log(students_scores); //顯示 [87, 27, 57] ``` ### 常用語法及內建函式 * `.length` 計算陣列的物件數 ```javascript= var score = [23, 24, 64, 83, 14]; console.log(score.length); // 顯示 5 ``` * `.length - 1` 取得最後一個物件值 ```javascript= var score = [23, 24, 64, 83, 14]; console.log(score[score.length - 1]); // 顯示 14 //因為都是從 0 開始數,所以要記得減 1 ``` * `.push() ` 在陣列末端加入值 ```javascript= var score = [23, 24, 64, 83, 14]; score.push(78); console.log(score); //顯示 [23, 24, 64, 83, 14, 78] ``` * `.join('')` 將陣列中的元素結合變成字串 ```javascript= let sentence = ['a', 'b', 'c']; let newSen = sentence.join('!'); // 指定用!連結(如果不指定會直接結合) console.log(newSen); // 得’a!b!c’ ``` * `.map(欲使用的函式)` 將陣列套入函式 ```javascript= let sentence = [1, 3, 5]; function triple (x) { return x * 3 } console.log(sentence.map(triple)); // [3, 9, 15] ``` 除此之外,`.map()` 可以累加使用,也可以使用**匿名函式**的方式。 ```javascript= let sentence = [1, 3, 5]; console.log(sentence .map(function (x) { return x * 3 }) .map(function (x) { return x * -2 }) ); // 最後得出 [-6, -18, -30] ``` * `.some(欲使用的函式)`:一樣也是將陣列套入函式 不一樣的地方是會回傳 boolean 值。如果是空陣列的話,會回傳 false。 ```javascript= const array = [1, 2, 3, 4, 5]; // 檢查是不是偶數 const even = (element) => element % 2 === 0; console.log(array.some(even)); // expected output: true ``` * `.filter(欲使用的函式)` 將陣列套入函式 > 不同於`.map()`的地方在於:return 值可套用邏輯,回傳為 true 才會留下,false 會捨去。 ```javascript= let sentence = [1, 3, 5, 0, -2, -4]; console.log(sentence .map(function (x) { return x * 3 }) .filter(function (x) { return x >= 0 }) ); // [3, 9, 15, 0] ``` 一開始先透過`.map()`套入 function,將元素全部乘以三後,再透過`.filter()`,過濾這些結果是否 >= 0。如果是的話,就會被回傳。所以這邊得到的是 [ 3, 9, 15, 0 ],-6 跟 -12 被捨棄了。 * `.slice(開始的索引值, 結束的索引值)` 取得陣列中的某段元素,開始的索引值會被包含、結束的不被包含。 > 如果不寫結束的索引值,會預設 -1,也就是直接取到最後一個。 ```javascript= let sentence = [1, 3, 5, 0, -2, -4]; console.log(sentence.slice(1, 4)); // 得 [3, 5, 0] ``` 開始的索引值 1 是 3,結束的索引值 4 是 -2,不過結束的索引值 -2 不包含。所以得 [3, 5, 0]。 * `.splice(開始刪除的索引值, 刪除幾個物件, 加入的物件)` 陣列的刪除、插入或更改元素 > 單純刪掉物件,則不需要填入第三個參數(加入的物件) > 如果再刪除幾個物件裡面填 0,就會是插入的功能。填 1 以上就會是更改的功能。 ```javascript= let sentence = [-1, 3, 5 , 7]; sentence.splice(1, 0, 2); console.log(sentence); // [-1, 2, 3, 5, 7] ``` 如上,從索引值 1 (3)開始刪除,但是因為第二個填入的是 0,所以不刪除,變成在 3 之前插入了 2。所以得 [-1, 2, 3, 5, 7]。 ```javascript= let sentence = ['Jan', 'Jul', 'Dec', 'Apr', 'May']; sentence.splice(1, 2, 'Feb','Mar'); console.log(sentence); // ['Jan', 'Feb', 'Mar', 'Apr', 'May'] ``` 如上,從索引值 1 (‘Jul‘)開始刪除,第二個填的是 2,所以刪除了 ‘Jul‘ 跟 ‘Dec‘,再加入 ’Feb‘ 跟 ‘Mar‘。所以得出的結果是 ['Jan', 'Feb', 'Mar', 'Apr', 'May']。 * `.sort()` 按照字母(a-z)或是數字(1-9)進行排序 > 按照開頭字母的順序及數字開頭的順序,並非按照數字大小 ```javascript= var months = ['March', 'Jan', 'Feb', 'Dec']; months.sort(); console.log(months); // ["Dec", "Feb", "Jan", "March"] var array1 = [1, 30, 4, 21, 100000]; array1.sort(); console.log(array1); //  [1, 100000, 21, 30, 4] ``` 如果希望陣列按照數字大小排序,由小排到大,可參考以下做法。 ```javascript= var arr = [1, 45, 100, 8]; arr.sort(function(a, b) { //可以先假設 a = 5 ,b = 1 方便比較 if (a === b) return 0 if (b > a) return -1 return 1 }); console.log(arr); //[1, 8, 45, 100] ``` 如果想要由大排到小,只需要將 b > a 改成 a > b 即可,其他不變。 * `forEach()` 將陣列內的每個元素,個個帶入函式中一次。 > 如果想要將陣列一個個印出、或是一個個套入函式中,不需要再寫迴圈,直接用`forEach()`即可。 ```javascript= var array1 = ['a', 'b', 'c']; array1.forEach(function(element) { console.log(element); }); // expected output: "a" // expected output: "b" // expected output: "c" ``` * `Array 名稱.indexOf('')` 找出該 array 中某東西的索引值。 ```javascript= var fruits = ['apple', 'orange', 'grape']; fruits.indexOf('mango'); // -1 找不到 fruits.indexOf('grape'); // 2 ``` ## 物件 Objects ### 特性 * 屬於物件型別,所以其屬於可變的 * 儲存於變數時,實際儲存的是記憶體位置 * 物件內部可以再放入物件或放入陣列 ### 使用方式 在大括號{}內存放各種不同性質的物件。特性為資料存取方式容易,常透過`.`來連接欲存取資料。 ```javascript= var student = { Name: 'Peter', Score: '67', Phone: '023313, Address: 'Taipei city', father:{ //在物件內加入物件 Name: 'Nick', Phone: '02345' } }; console.log(student.father.Phone); // '02345' ``` 也可透過中括號 [ ] 存取資料,但較不常見。 ```javascript= var student = { Name: 'Peter', Score: '67', Phone: '023313', Address: 'Taipei city', }; console.log(student['Name']); // 'Peter' ``` ### 常用語法與內建函式 * 新增物件內容 ```javascript= var student = []; var Peter = { Score: '67', Phone: '023313', } Peter.Address = 'Taipei city'; student.push(Peter); console.log(student); // [ { Score: '67', Phone: '023313', Address: 'Taipei city' } ] ``` 直接透過 `Peter.Address = 'Taipei city';` 新增物件的 Address 內容。 * `delete` 刪除物件內容 ```javascript= var student = []; var Peter = { Score: '67', Phone: '023313', Address: 'Taipei city', } delete Peter.Score; console.log(student); // [ { Phone: '023313', Address: 'Taipei city' } ] ``` * 將物件放入陣列中 ```javascript= var student = [ ] var Peter = { Name: 'Peter', Score: '67', Phone: '023313', Address: 'Taipei city', }; student.push(Peter); console.log(student[0].Score); // '67' ``` ## 迴圈 Loop ### Do...While 迴圈 do while 迴圈有兩種用法。先假設我們想要印出 1 到 5。 第一種用法: ```javascript= let i = 1; // 宣告變數 i 等於 1 do { // 啟動 do 迴圈 console.log(i); // 印出 i 值 i++ // 印完之後 i + 1 } while (i <= 5) // 如果 i <= 5 就繼續 do 迴圈 /* 1 2 3 4 5 */ ``` 第二種用法: ```javascript= let i = 1; // 宣告變數 i 等於 1 do { // 啟動 do 迴圈 console.log(i); // 印出 i 值 i++ // 印完之後 i + 1 if (i > 5) { // 結束條件出現:如果 i 大於 5 break // 就跳出迴圈(如果 i 沒有大於五,就繼續迴圈) } } while (true) /* 1 2 3 4 5 */ ``` * `break` : 中斷,並跳出該 loop。 * `continue` :一般來說如果迴圈搭配條件式使用,如果找到要找的值,就會停止繼續找剩下的了。`continue` 的用意就是即便找到了,繼續將剩餘的找完 (執行到 `continue` 的話,會跳過 `continue` 的下一行指令(依照以下範例的話是跳過 `console.log('不是第' + i + '個,第' + i + '個是' + arr[i])`),切換到` while` 繼續執行)。 continue 範例:找出陣列中的值的索引值 ```javascript= var arr = [1, 5, 8, 12, 50, 99, 7, 20] var i = 0 do { i++ if ( arr[i] === 50 ) { console.log('抓到了 50 ! 他在第' + i + '個 !') continue } console.log('不是第' + i + '個,第' + i + '個是' + arr[i]) } while ( i < arr.length - 1 ) /*不是第1個,第1個為5 不是第2個,第2個為8 不是第3個,第3個為12 抓到了 50 ! 他在第4個 ! //一般來說沒有使用 continue 會只抓到這裡 不是第5個,第5個為99 //但是因為使用了 continue 所以繼續跑了 不是第6個,第6個為7 不是第7個,第7個為20 */ ``` ### While 迴圈 目標:印出 1-5。 ```javascript= let i = 1; //初始值 i = 1 while (i <= 5) { // i <= 5 的時候執行以下內容(結束條件) console.log(i); // 將 i 印出 i++ } /* 1 2 3 4 5 */ ``` 簡單來說就是將剛剛的 do while 迴圈的 do 刪掉,將 while 的條件移到前面,其他不變。 ### For 迴圈 目標:印出 1-5。 ```javascript= for(i = 1; i <= 5; i++) { // for(初始值; 結束條件; 每圈結束要做的事) console.log(i); } /* 1 2 3 4 5 */ ``` 另一種 for 迴圈寫法,稱為 `for...of`。 ```javascript= const array1 = ['a', 'b', 'c']; // 將陣列內的元素取名成 element for (const element of array1) { console.log(element); } // expected output: "a" // expected output: "b" // expected output: "c" ``` ## 函式 Function ### 結構介紹 函式就有點像數學中的 f(x),所以這邊先以數學的 f(x) 為例。 ``` f(a, b, c) = a + 2b + 3c f(1, 2, 3) = 14 f(1, 1, 1) = 6 ``` 以下是程式中的函式。 ```javascript= function abc(a, b, c) { return a + 2 * b + 3 * c; // return + 藉由函式完成的內容  } console.log(function abc(2, 3, 4)); // 20 ``` function 為函式。函式名稱:abc。參數:a, b, c。 ### 注意事項 * 回傳值為物件時,務必將大括號放置在 return 後,再接續放置物件。若是將大括號放在隔行,會顯示錯誤訊息(undefined)。範例如下。 ```javascript= function double(x) { return { // 大括號一定要放在這 answer: x * 2 } } console.log(double(5)); // { answer: 10 } ``` * function 內可以可以再放 function ```javascript= function print(anything) { // 有一個 print function anything(); // 填入的參數就是執行那個 function } function hello() { // 有一個 hello function console.log('hello'); // 印出 'hello' } print(hello) // 先呼叫 print function,再透過 print function 呼叫 hello function // 最後印出 hello ``` * 傳值要小心,以下提供兩個範例。 ```javascript= function add(obj) { obj.number++ return 1 } let obj = { number: 10 } console.log(add(a)); // add funtion 回傳值是 1 // 1 ``` 兩個範例只差在最後的兩行。 > 上面的將 add function 直接放入 `console.log()` 裡,下面的先執行 add function 後,再印出 a。 這樣的小差別,卻可以讓兩個的答案完全不同。 ```javascript= function add(obj) { obj.number++ return 1 } let obj = { number: 10 } add(a) // 執行 add function,執行內容是將 a 這個物件的 number 的元素 + 1 console.log(a); // 經過剛剛執行後現在 a = 11 // 11 ``` ### 以陣列形式建構函式 目標:建構一個輸入 10 就會回傳 [1, 2, 3, 4,..10] 的陣列函式。 ```javascript= function generateArray(n) { var result = []; // 宣告一個空陣列 for (let i = 1; i <= n; i++) { result.push(i); // 將 i 值一個個放入 result 陣列中 } return result } console.log(generateArray(5)); // [ 1, 2, 3, 4, 5 ] ``` > 陣列型式也可與 function 內可結合 function 的功能結合,如下: ```javascript= function transform(arr, transformFunction) { var result = []; for(let i = 0; i < arr.length; i++) { result.push(transformFunction(arr[i])); } // 將 arr 的值一個個帶入函式後的結果放入 result 陣列中 return result } function double(x) { return x * 2 } console.log( transform([1, 3, 5], double) ); // [ 2, 6, 10 ] ``` ### 宣告函式的其他方法 我們先來看一般宣告函式的方法。 ```javascript= function triple(x) { return x * 3 } ``` #### 宣告一變數 = 函式 如標題,先宣告一個變數,再將此變數賦值給一個函式。 ```javascript= let triple = function(x) { return x * 3 } ``` #### 匿名函式 Anonymous Function 顧名思義,匿名函式就是沒有名字的函式。會直接將名字省略,所以通常在使用此函式時不需要先寫一個函式、應用時套用參數,欲使用時直接將整個函式寫出來即可。 ```javascript= // let triple = function(x) { // return x * 3 // } // 不需要像以上寫出函式 function accar(arr, accarFunc) { newArr = []; for (let i = 0; i < arr.length; i++) { newArr.push(accarFunc(arr[i])); } return newArr; } console.log( accar([2, 4, 6], function(x) { // 這裡就是匿名函式 return x * 3 //直接寫下函式內容即可 }) // 這樣的函式功能與前三行被備註掉的函式功能一樣 ); // [ 6, 12, 18 ] ``` ### 參數(parameter)和引數(argument) 什麼是參數跟引數呢?看個範例就知道了。 ```javascript= function add(a, b) { return a + b; } const c = 10; const d = 20; add(c, d); ``` 參數是範例中的 a 跟 b。引數是實際案例中的 c (10)跟 d(20)。 > 引數(argument)跟 array 很像,是個類陣列 (array-like) 的物件,可被放入 function 內。 ```javascript= function PrintArgu(a, b) { console.log(arguments); } PrintArgu(3, 4, 5); // [Arguments] { '0': 3, '1': 4, '2': 5 } ``` 依照上面的這個範例,我們可以看出來 arguments 確實是個類陣列的物件。因此我們可以透過這個特性,去做相關利用。 ```javascript= function PrintArgu(a, b) { console.log(arguments[1]); // 取 arguments 索引值 1 的內容 } PrintArgu(3, 4, 5); // 4 ``` ## 常用內建函式 ### 數字相關 * `Number()` 將字串轉換為數值 ```javascript= var a = 10; var b = '20'; console.log(a + Number(b)); // 30 ``` * `.toString()` 將數值轉換成字串 ```javascript= var a = 10; let b = '50'; console.log(a.toString() + b); // 1050 ``` * `parseInt(參數,幾進位的參數)` 將字串轉換成整數 > 若沒寫第二個參數預設十進位 ```javascript= var a = 10; var b = '20'; console.log(a + parseInt(b)); // 30 ``` * `parseFloat(參數)` 將字串轉換為小數 ```javascript= var a = 10; var b = '20.26'; console.log(a + parseFloat(b)); // 30.26 ``` * `.toFixed(到小數第幾位)` 將小數點捨去到指定的位數 > 剩餘的小數點會自動四捨五入 ```javascript= var a = 10; var b = '20.268352'; console.log(parseFloat(b).toFixed(3)); // 20.268(後面的會四捨五入) ``` > 若是不填參數預設全部捨去 ```javascript= var a = 10; var b = '20.268352'; console.log(parseFloat(b).toFixed()); // 20 ``` * `Number.MAX_VALUE` 列出記憶體可儲存的最大數值 ```javascript= console.log(Number.MAX_VALUE); // 會出現1.7976931348623157e+308 // 代表數字最多可到三百多位,一旦超過這個位數計算就會不精準 ``` * `Number.MIN_VALUE` 列出記憶體可儲存的最小數值 ```javascript= console.log(Number.MAX_VALUE); //會出現5e-324 // 代表數字最多可到小數點後三百多位,一旦超過這個位數計算就會不精準 ``` * `Math.PI` 印出常數 π > PI 是常數(constant),固定不會變的值,通常以大寫表示 ```javascript= console.log(Math.PI); // 3.141592653589793 console.log(Math.PI.toFixed(4)); // 3.1416 ``` * `Math.ceil()` 小數點無條件進位成整數 ```javascript= console.log(Math.ceil(12.35)); // 13 ``` * `Math.floor()` 小數點無條件捨去成整數 ```javascript= console.log(Math.floor(12.35)); // 12 ``` * `Math.round()` 小數點四捨五入成整數 ```javascript= console.log(Math.round(12.35)); // 12 console.log(Math.round(12.55)); // 13 ``` * `Math.sqrt()` 開根號 ```javascript= console.log(Math.sqrt(16)); // 4 console.log(Math.sqrt(20)); // 4.47213595499958 ``` * `Math.max(可放多個參數)` 取最大值 ```javascript= console.log(Math.max(1, 3, -5)); // 3 ``` * `Math.min(可放多個參數)` 取最小值 ```javascript= console.log(Math.min(-1, 10, -2)); // -2 ``` * `Math.pow(參數, 的幾次方)` 取參數的幾次方 ```javascript= console.log(Math.pow(2, 5)); // 32 ``` * `Math.random()` 隨機取得 0 到小於 1 之間的數(也就是 0 - 0.999…) ```javascript= console.log(Math.random()); // 0.3747946876975716 console.log(Math.random() * 10); // 3.7667189027459913 ``` 那如果我們想要用此語法製作出隨機選出 1 - 10 的數呢? 或許我們可以套用之前學的無條件捨去 ─ `Math.floor()`。 ```javascript= console.log(Math.floor(Math.random() * 10)); // 0 // 因為也是有可能隨機選到 0.000...的值,即便 * 10 還是 0 console.log(Math.floor(Math.random() * 10 + 1)); // 2 // 所以可以全數 + 1,解決此問題 ``` 透過此語法也可以自己定義出隨機選值的範圍。 ### 字串相關 * `.toUpperCase()` 全數轉成大寫 ```javascript= var a = 'aBc'.toUpperCase(); console.log(a); // ABC ``` * `.toLowerCase()` 全數轉成小寫 ```javascript= var a = 'AbC'.toLowerCase(); console.log(a); // abc ``` * .`charCodeAt(字串索引)` 可得字母的數字值 ```javascript= var alphbat = 'ABC'; console.log(alphabat.charCodeAt(1)); // 66 (得出大寫 B 的 CharCode 是66) ``` * `String.fromCharCode()` 從數值轉換成字母 ```javascript= var str = String.fromCharCode(66, 98, 75); console.log(str); // BbK ``` > charCode 字母大寫跟小寫都會差 32,小寫比大寫大,像剛剛 B 是 66,小寫 B = 66 + 32 = 98。可以利用這個固定差取得大寫字母或小寫字母。 ```javascript= var a = 'Pat';  // 先宣告一個變數 var aCode = a.charCodeAt(1); // 取出'a'的數值 var str = String.fromCharCode(aCode - 32); // 將 a 的數值 - 32 = 大寫,再將此值轉成字母並存入str console.log(str); // 得出 A ``` * `.indexOf(要找的東西)` 得出要找的東西的索引。 ```javascript= var greeting = 'My name is Valen. Nice to meet you!'; var aCode = greeting.indexOf('is'); console.log(aCode); // 8 ``` 那如果沒找到呢? 會回傳 -1。 ```javascript= var greeting = 'My name is Valen. Nice to meet you!'; var aCode = greeting.indexOf('he'); console.log(aCode); // -1 //不存在的東西都會是 -1 ``` 這個特性可以搭配條件式使用,如果 >= 0 等於存在,如果 <0 等於不存在。 ```javascript= let sentence = 'Hello! Nice to meet you.'; if (sentence.indexOf('he') >= 0) { console.log('"he" is existed.') } else { console.log('"he" is not existed.') } // "he" is not existed. ``` * `.replace(被取代的字串, 新的欲放入的字串)` 取代字串 > 只會取代一次 ```javascript= let sentence = 'Hello nice to meet you.'; let newSen = sentence.replace('e', 'i'); // 將 e 改成 i console.log(newSen); // Hillo nice to meet you. // 只取代了 hello 的 e,nice 的 e 並沒有取代 ``` 那該如何取代多個呢?`/ 被取代的字串/g `(global) ```javascript= let sentence = 'Hello nice to meet you.'; let newSen = sentence.replace(/e/g, 'i'); //將所有的e改成i console.log(newSen); // 得Hillo nici to miit you. ``` * `.trim()` 將前後空格去掉 ```javascript= let sentence = ' Hello nice to meet you. '; let newSen = sentence.trim(); console.log(newSen); // Hello nice to meet you. ``` * `.split(以此切開的字串)` 將字串切開並放入陣列 ```javascript= let sentence = 'Hello nice to meet you.'; let newSen = sentence.split(' '); //以空格來切 console.log(newSen); // [ 'Hello', 'nice', 'to', 'meet', 'you.' ] ``` ◎ 讀取 csv 格式時,很常是以逗號分割,如 data1, data2, data3 等等,這時就可以使用。若前後有空格,可搭配`.trim()`使用 * `.length` 得總共有幾個字(包含空格或符號) ```javascript= let sentence = 'Hello nice to meet you.'; let newSen = sentence.length; console.log(newSen); // 23(包含括號及句號總共 23 個字) ``` ## Debugger 碰到 bug 的時候可以透過瀏覽器的 debugger 一行行的將程式碼跑過,透過視覺化的方式了解跑程式的過程。 ### 環境 必須在 Chrome 中使用。可先在 cmder 建立一個 html 檔案,並透過 vim 編輯後從 Chrome 打開。以下提供範例內容。 ```htmlmixed= <Script> debugger //在想要透過 debugger 跑的地方前輸入 debugger var i = 1; do { console.log(i); i++ } while(i <= 5); </Script> ``` 在 Chrome 中打開 dev tools 後點開 Sources 標籤,重新整理就會看到游標跑在 debugger 上。以下為圖示。 ![](https://i.imgur.com/CWQqe17.jpg) 1. console:在 debugger 過程中可隨時切換至 console 確認進度。 2. 暫停與繼續執行鍵。 3. 開始 debugger 功能。 4. 輸入想確認的值。像是在此可輸入 i。