---
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)
```

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

# 陸、箭頭函示與傳統函式
### 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);
```

- 使用展開後,所有的資料都會並列在同一個陣列裡面。
```javascript=
//回傳一個新的陣列,並加入 icash
const newPeople3 = people.map(function(item, index, array){
return{
...item,
icash : item.money+500,
}
})
console.log(newPeople1);
```

- map **不適合**用來過濾陣列,因為有沒有符合條件,他都會 return 值,沒符合條件傳回來的值會變成 undefined。
```javascript=
const newPeople = people.map(function(item, index, array){
if(item.money > 500){
return{
...item,
}
}
})
console.log(newPeople);
```

### 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);
```