###### 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。