---
# System prepended metadata

title: JavaScript ES6 筆記

---

---
title: 'JavaScript ES6 筆記'
disqus: Pai
---


# 壹、目錄及代辦事項



## Table of Contents

[TOC]

## 待學習項目
- [ ] - 
- [ ] - 
- [ ] -
- [ ] - 
# 貳、使用 let 與 const 宣告變數
### 1. 使用 var 與 let 的不同

- 因為 Hoisting(提升) 的關係，這個結果第一個 console.log 會出現 undefined。
- 記憶題已經為 mom 這個變數準備了記憶體的位置
```javascript=
console.log(mom);
var mom = '老媽';
(function () {
  console.log(mom);
})();
//undefined
//老媽
```

- 這個結果則會出現 Uncaught ReferenceError ，告訴你你還沒宣告這個變數。

```javascript=
console.log(mom);
let mom = '老媽';
(function () {
  console.log(mom);
})();
```

### 2. 使用 var 與 let 作用域的差異
    var 的作用域是 function scope: var 的作用域會在整個 funciton 裡面
    let 的作用域是 block: 指 let 的作用域就指在它存在的 {} 內

#### a. 使用 var 的時候，因為作用域在整個 function 內，所以在 if(true) 裡面宣告，ming 的結果會改變。

```javascript=
function varMing () {
  var ming = '小明';
  if (true) {
    var ming = '杰哥';  
  }
  console.log(ming);  
}
varMing ()// '杰哥'
```

#### b. 使用 var 的時候，因為作用域只限制在 let 所在的 {} 裡面，不會改變到外層的變數。


- 範例一
```javascript=
function varMing () {
  let ming = '小明';
  if (true) {
    let ming = '杰哥';  
  }
  console.log(ming);  
}
varMing ()// '小明'
```


- 範例二
   
   - 因為 i 的作用域在整個 function{} 內，console 和 setTimeout 是同時執行的，console 馬上就執行完畢了，但 setTimeout 要等三秒，三秒過後，i 得到的值就是最後全域變數裡的 10 了。
   - 而 i 不是只到 9 嗎? 為什麼最後的結果會呈現 10，這是因為 i 吃到全域變數的值，而 i 在執行第 10 次時，因為條件不符合，就沒有繼續執行{}內的內容，不過在 window i 就紀錄為 10 了。
```javascript=
for (var i = 0; i < 10; i++) {
  console.log(i);
  setTimeout(function () {
    console.log('這執行第' + i + '次');
  }, 3000);
}
// 1,2,3,4,5,6,7,8,9
//這執行第 10 次
```
-
    - 當把 var i = 0 改成 let i = 0，最主要影響 setTimeout中輸出 i 的值，原因是使用 let 宣告變數的話，會有區塊作用域的特性，因此每一次迭代都會重新綁定，所以 setTimeout 在時間倒數結束後，區塊作用域會是當時候的變數 i 值．
```javascript=
for (let i = 0; i < 10; i++) {
  console.log(i);
  setTimeout(function () {
    console.log('這執行第' + i + '次');
  }, 3000);
}
// 1,2,3,4,5,6,7,8,9
//這執行第1次
//這執行第2次
//這執行第3次
//這執行第4次
//這執行第5次
//這執行第6次
//這執行第7次
//這執行第8次
//這執行第9次
```

#### b. 如何在 var 的情況下做出與用 let 宣告的效果
```javascript=
for (var i = 0; i < 10; i++) {
  console.log(i);
  setTimeout(function () {
    console.log('這執行第' + i + '次');
  }, 3000);
}
// 1,2,3,4,5,6,7,8,9
//這執行第 10 次
```
使用立即函式
```javascript=
for (var i = 0; i < 10; i++) {
  console.log(i);
  (function(i){setTimeout(function () {
    console.log('這執行第' + i + '次');
  }, 3000)})(i);
}
```

### 3. const 常數
#### a. const 宣告後值就不能被修改
```javascript=
const ming = '鐵錚錚男子漢';
ming= '騙人';

//這樣就會出現錯誤
```
#### b.但是用 const 宣告的物件是可以修改的
因為物件是傳參考，只要沒有把參考值替換掉，就可以修改
```javascript=
const family = {
  mom: '老媽',
  me: '小明',
  sister: '小橙'
};
family.mom = '爸爸';
//{mom: "爸爸", me: "小明", sister: "小橙"}
```

# 参、展開與其餘參數

### 1. 使用展開語法，合併陣列
- ES5 的語法
```javascript=
let groupA = ['小明', '杰倫', '阿姨'];
let groupB = ['老媽', '老爸'];
let groupAll = groupA.concat(groupB);
console.log(groupAll);// ["小明", "杰倫", "阿姨", "老媽", "老爸"]
```
- 使用 ES6 展開語法
    - ...就是把陣列裡面的值一個一個取出來，例如:小明 杰倫 阿姨
```javascript=
let groupA = ['小明', '杰倫', '阿姨'];
let groupB = ['老媽', '老爸'];
let groupAll = [...groupA,...groupB];
console.log(groupAll);// ["小明", "杰倫", "阿姨", "老媽", "老爸"]
console.log(...groupA); //小明 杰倫 阿姨
```
### 2. 淺複製觀念說明 (shallow copy)
陣列和物件都有傳參考的特性，運用...可以淺複製出另一個陣列，就可以獨立於原陣列產生一個新陣列。
```javascript=
let groupA = ['小明', '杰倫', '阿姨'];
let groupB = [...groupA];
groupB.push('阿明');
console.log(groupA); //["小明", "杰倫", "阿姨"]
console.log(groupB); //["小明", "杰倫", "阿姨", "阿明"]
```

### 3. 類陣列的觀念講解
- 當傳入的值 updateEasyCard()，沒有給變數時，傳入的值都會被放在 arguments 裡面
- 這邊的 arguments 為類陣列，並非真正的陣列。
- 但要使用 reduce，前面的 arg 必須是陣列，因此使用 [...arguments] 將arg 轉為陣列。
```javascript=
var originCash = 1000;
function updateEasyCard() {
  let arg = [...arguments];
  let sum = arg.reduce(function (accumulator, currentValue) {
    return accumulator + currentValue;
  }, 0);
  console.log('我有 ' + sum + ' 元');
}
updateEasyCard(0); // 我有 1000 元
updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500); // 我有 718 元
```

### 4. 其餘參數
- 有些時候傳入參數時，並不確定參數有多少，這時就可以使用到'其餘參數'。
- 下面的範例，money 的參數就會自動以陣列的方式呈現。
```javascript=
function moreMoney(...money) {
  console.log(money); //[100, 100, 100]
}
moreMoney(100, 100, 100)
```
- 也可以前面有變數，後面不確定數量的值使用其餘參數。
```javascript=
function moreMoney(ming,...money) {
  console.log(ming); //小明
  console.log(money); //[100, 100, 100]
}
moreMoney('小明',100, 100, 100)
```

# 肆、解構賦值
### 1. 賦值
- 原本使用 ES5 時，將陣列的值拿出來賦於另一個變數要這樣做
```javascript=
let family = ['小明', '杰倫', '阿姨', '老媽', '老爸'];
let ming = family[0];
let jay = family[1];
let auntie = family[2];
```
- 如果使用 ES6 解構賦值的特性，變數就可以被快速賦值上去
```javascript=
let family = ['小明', '杰倫', '阿姨', '老媽', '老爸'];
let [ ming , jay , aunt , mom , dad ]= family;
console.log(ming , jay , aunt , mom , dad);
//小明 杰倫 阿姨 老媽 老爸
```

- 假如左右數量不對等時，就只會呈現左方出現變數的名稱
```javascript=
let family = ['小明', '杰倫', '阿姨', '老媽', '老爸'];
let [ ming , jay , aunt]= family;
console.log(ming , jay , aunt);
//小明 杰倫 阿姨 
```

- 當中間值有缺少時，阿姨的值就不會進行解構賦值
```javascript=
let family = ['小明', '杰倫', '阿姨', '老媽', '老爸'];
let [ ming , jay ,, mom , dad ]= family;
console.log(ming , jay , mom , dad);
```

- 設定預設值：當 value 有缺少時，可以使用預設值來填補
```javascript=
let family = ['小明', '杰倫', '阿姨', '老媽'];
let [ ming , jay , aunt , mom , dad='老爸' ]= family;
console.log(ming , jay ,aunt , mom , dad);
// 小明 杰倫 阿姨 老媽 老爸
```

- 其餘部分：可以其餘剩餘的部分放在...other 裡面
```javascript=
let family = ['小明', '杰倫', '阿姨', '老媽'];
let [ ming , ...other ]= family;
console.log(ming , other);
//小明  ["杰倫", "阿姨", "老媽"]
```

- 忽略元素: 單獨要取某個值時，可以使用,數量來取得
```javascript=
let family = ['小明', '杰倫', '阿姨', '老媽'];
let [ ,, aunt]= family;
console.log(aunt);
// 阿姨
```

### 2. 使用解構賦值來交換兩個變數的內容
```javascript=
let Goku = '悟空';
let Ginyu = '基紐';
[ Goku , Ginyu ] = [ Ginyu , Goku ]
console.log(Goku,Ginyu);//基紐 悟空
```

### 3. 使用解構賦值將字串的一個個字元取出來
```javascript=
let str = '基紐特攻隊';
let [a,b,c,d,e] = str;
console.log(a,b,c,d,e); //基 紐 特 攻 隊
```

### 4. 取出其中一個值，並附在新的變數名稱上
將 Ginyu 的變數替換為 Guku
```javascript=
let GinyuTeam = {
  Ginyu: '基紐',
  Jeice: '吉斯',
  burter: '巴特',
  // ...
}

let {Ginyu:Guku} = GinyuTeam;
console.log(Guku); //基紐
```

### 5. 請取出物件內的兩個值到單一變數上
淺拷貝
```javascript=
let family = {
  ming: '小明',
  jay: '杰倫',
};

let familyAll = { ...family }
console.log(familyAll); //{ming: "小明", jay: "杰倫"}
```

### 6. 延伸問題
```javascript=
let { ming: Goku, family: [, mom] } = { ming: '小明', family: ['阿姨', '老媽', '老爸'] }
console.log(Goku, mom); // 小明 老媽
```

### 7. 預設值的概念
```javascript=
let [ming = '小明', jay = '杰倫'] = ['阿明'] 
// 第一個會被賦值，第二個會用預設
console.log(ming,jay); //阿明 杰倫
```
### 8. 替換加上預設值
```javascript=
let { family: ming = '小明' } = {family:'小強'}
console.log(ming) //小明
```
### 9. 解構函式參數: 再帶入參數值時，直接將物件解構
```javascript=
// function distance(point){
//     const [x, y] = point
//     return Math.sqrt(x*x+y*y);
// }
function distance([x, y]){
    return Math.sqrt(x*x+y*y);
}
const point = [1, 3]
distance(point);
```

# 伍、縮寫
### 1. 請將以下兩個合併至一個物件上
- 這時，如果賦值的變數是一樣的，就可以不重複寫。
- 這邊的屬性有淺拷貝
```javascript=
const Frieza = '弗利沙'
const GinyuTeam = {
  Ginyu: '基紐',
  Jeice: '吉斯',
  burter: '巴特',
  // ...
}

const newTeam = {
  Frieza : Frieza, -> Frieza,
  GinyuTeam : GinyuTeam -> GinyuTeam
}
console.log(newTeam);
```

### 2. 物件函式的縮寫
只能用在物件內喔。
```javascript=
const newTeam = {
  // ...
  showPosture: function () {
    console.log('我們是 基紐特戰隊')
  }
}
newTeam.showPosture();
//可以改成 

const newTeam = {
  // ...
  showPosture() {
    console.log('我們是 基紐特戰隊')
  }
}
newTeam.showPosture();
```

### 3. 搭配解構使用縮寫
原本只有使用縮寫，會再包一層
```javascript=
const GinyuTeam = {
  Ginyu: {
    name: '基紐'
  },
  Jeice: {
    name: '吉斯'
  },
  burter: { 
    name: '巴特'
  },
  // ...
}
const newTeam = {
  GinyuTeam,////<----------只有縮寫，這邊有淺拷貝
}
newTeam.ming="小明";

console.log('newTeam',newTeam,'GinyuTeam',GinyuTeam)
```
![](https://i.imgur.com/XENh75g.png)

搭配解構後
```javascript=
const GinyuTeam = {
  Ginyu: {
    name: '基紐'
  },
  Jeice: {
    name: '吉斯'
  },
  burter: { 
    name: '巴特'
  },
  // ...
}
const newTeam = {
  ...GinyuTeam,////<----------搭配解構
}
newTeam.ming="小明";

console.log('newTeam',newTeam,'GinyuTeam',GinyuTeam)
```
![](https://i.imgur.com/bry38v4.png)

# 陸、箭頭函示與傳統函式
### 1. 基本的箭頭函式
```javascript=
var callSomeone = (someone) => {
  return someone + '吃飯了'
}
console.log(callSomeone('小明'))
```
- 如果函式內榮只有一行就可以再簡化，把 ()、return、{} 花括號拿掉

```javascript=
var callSomeone = someone => someone + '吃飯了'
console.log(callSomeone('小明'))
```
- 如果預期不帶入參數，()就不能省略
```javascript=
var callSomeone = () => someone + '吃飯了'
console.log(callSomeone())
```
### 2. 箭頭函式裡面沒有 argument 這個參數
```javascript=
const updateEasyCard = () => {
  let cash = 0;
  console.log(argument); // arguments is not defined
}
updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500);
//不能執行，箭頭函式裡面沒有 argument 這個參數
```
- 要改寫為其餘參數
```javascript=
const updateEasyCard = (...arg) => {
  let cash = 0;
  console.log(arg); // arguments is not defined
}
updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500);
```
### 3. 箭頭函式裡面的 this 都會指向全域變數
### 4. 在 Vue 的 methods 裡面使用傳統函式，可以使用縮寫的方式

# 柒、字串模板 Template String
### 1. ${ } 放入的是表達式

表達式是什麼？ 表達式是一段可以很長，但會產生結果值的程式碼，而且很常是運算式
```javascript=
1 + 2

functionInvocation()

ture || false d

true && true

a = 3  //會回傳 3 

a === 3

Array.isArray([]) ? doSomeThing() : doOtherThing() 
```
陳述式是什麼？ 陳述式一定會做一些事情，但陳述式不會產生數值
下面這些都是 JavaScritp 裡的陳述式：

- 變數宣告

- if 判斷式

- while 迴圈

- for 迴圈

- switch 判斷是

- for-in 迴圈

- 直接的函式宣告
```javascript=
var a = 3 ;

if(a === 3){
//doSomeThing...
}

{
//doSomeThing , this is a Block Statement
}

for (var i = 0 ; i<=10 ; i++ ){
//doSomeThing
}

try{
...
}catch (){
...
}
```

使用表達式的範例
```javascript=
// 在 ＄{} 內直接做運算
function greet(name, days){
    // const hours = days*24;
    console.log(`Hello, ${name}. It's been ${days*24} hours`)
}
greet('Jack', 3)

// 在 ＄{} 內做三元判斷式
function greet(name, days){
    console.log(`Hello, ${name}. ${(days < 7)?'':'Long time no see'})
}
greet('Jack', 3)
// Hello, Jack.
greet('Mary', 14)
// Hello, Mary. Long time no see
```

### 2. 字串模板裡面也可以寫 JavaScript
```javascript=
const people = [
  {
    name: '小明',
    friends: 2
  },
  {
    name: '阿姨',
    friends: 999
  },
  {
    name: '杰倫',
    friends: 0
  }
]
let originUl = `
<ul>
  ${people.map(item => `<li>我叫做 ${ item.name }</li>`).join('')}
</ul>`;
console.log(originUl);
```
# 捌、操作陣列的方法

### 1. foreach

- foreach 的功能跟 for 迴圈是一樣的。一樣會把陣列全部跑一遍。
**array.forEach(function(item, index, array){...}**
    item: 陣列中的物件
    index: 索引
    array: 整個陣列

```javascript=
const people = [
  {
    name: '小明',
    money: 500
  },
  {
    name: '漂亮阿姨',
    money: 3000
  },
  {
    name: '杰倫',
    money: 60000
  },
  {
    name: '老媽',
    money: Infinity
  }
];

people.forEach(function(item, index, array){
  item.cash = item.money + 500;
  console.log(item);
})
```

### 2. map
- map 的作用基本和 foreach 一樣。但 map 會有 return 回傳值。


```javascript=
const people = [
  {
    name: '小明',
    money: 500
  },
  {
    name: '漂亮阿姨',
    money: 3000
  },
  {
    name: '杰倫',
    money: 60000
  },
  {
    name: '老媽',
    money: Infinity
  }
];

people.map(function(item, index, array){//只是把 foreach 改 map
  item.cash = item.money + 500;
  console.log(item);
})
```

- 唯一不同的是，他會回傳值。回傳的值可以變成一個新的陣列。
```javascript=
//回傳一個新的陣列
const newPeople1 = people.map(function(item, index, array){
  return item;
})
console.log(newPeople2);
```
- 如果沒有使用展開，回傳的陣列中，people 的物件會另外被包在 item 的物件裡面， icash則獨立分開。
```javascript=
//回傳一個新的陣列，並加入 icash
const newPeople2 = people.map(function(item, index, array){
  return{
    item,
    icash : item.money+500,
  }
})
console.log(newPeople);
```
![](https://i.imgur.com/V0yq00j.png)

- 使用展開後，所有的資料都會並列在同一個陣列裡面。
```javascript=
//回傳一個新的陣列，並加入 icash
const newPeople3 = people.map(function(item, index, array){
  return{
    ...item,
    icash : item.money+500,
  }
})
console.log(newPeople1);
```
![](https://i.imgur.com/Y8gJEbV.png)
- map **不適合**用來過濾陣列，因為有沒有符合條件，他都會 return 值，沒符合條件傳回來的值會變成 undefined。
```javascript=
const newPeople = people.map(function(item, index, array){
  if(item.money > 500){
    return{
      ...item,
    }
  }
})
console.log(newPeople);
```
![](https://i.imgur.com/6DSspS8.png)

### 3. filter
- filter 用來過濾條件為 true 的值。
```javascript=
const filterArr = people.filter(function(item,index){
  if(item.money < 5000){
    return true;
  }
  //也可以改寫為 return item.money < 5000
})
console.log(filterArr);
//{name: "小明", money: 500} {name: "漂亮阿姨", money: 3000}
```

### 4. find
適合用來尋找單一條件， find 只會回傳一個值。像找 id 等特定值就很適合。
```javascript=
const findArr = people.find(function(item,index){
  if(item.money < 5000){
    return true;
  }
})
console.log(findArr);
//{name: "小明", money: 500}
```

### 5. every
- 回傳值只回 true 或 false。
- 回傳 true 的條件必須是所有值都滿足條件，否則回傳 false
```javascript=
const ans = people.every(function(item,index){
    return item.money >3000;
})
console.log(ans);
// false
```

### 6. some
- 回傳值只回 true 或 false。
- 回傳 true 的條件最少只要有一個值滿足條件，全部不符則回傳 false
```javascript=
const ans = people.some(function(item,index){
    return item.money >3000;
})
console.log(ans);
//true
```

### 7. reduce
reduce(function(prev,item,index){...}, default)
prev: 前一個值，如果沒有前一個值就使用 default
item: 目前的值
index: 索引
```javascript=
const people = [
  {
    name: '小明',
    money: 500
  },
  {
    name: '漂亮阿姨',
    money: 3000
  },
  {
    name: '杰倫',
    money: 60000
  }
];

const num = people.reduce(function(prev,item,index){
  console.log(prev);
  return prev+item.money;
},0)
console.log(num);
//0(prev)
//500(prev)
//3500(prev)
//63500(num)
```
- 使用 reduce 做比大小的運用
```javascript=
const num = people.reduce(function(prev,item,index){
  console.log(prev);
  return Math.max(prev,item.money); //拿前一個值和目前值比較大小
},0)
console.log('Max:',num);
```
