owned this note
owned this note
Published
Linked with GitHub
# JavaScript - ES6 語法、Babel 轉譯器
###### tags: `Tag(程式基礎)`
### ES5 VS ES6
- <font color="99b898">**ECMAScript 5 ( ES5 )**</font>:ECMAScript 的第五版,於 2009 年發佈。
- <font color="99b898">**ECMAScript 6 ( ES6 )**</font>:ECMAScript 的第六版,於 2015 年發佈。
>[參考資料](https://ithelp.ithome.com.tw/articles/10206587) 淺談JS版本差異!ES5、ES6
## let, const 跟 var 的比較跟應用
變數宣告新用法: let、const ( ==區塊作用域 block scope== )
>相較於 ES5 的變數宣告只有 var, ==ES6 多了 let 跟 const 可以用,重點多了作用域的不同。==
每個變數在宣告時,都只會==在執行環境內建立記憶體,這個就是他的作用域==
:::warning
>[參考資料](https://medium.com/when-you-feel-like-quitting-think-about-why-you/javascript-3-%E7%AF%84%E7%96%87-scope-%E6%9A%AB%E6%99%82%E6%AD%BB%E5%8D%80-tdz-%E5%AE%A3%E5%91%8A%E8%AE%8A%E6%95%B8-5adcf6302852) JavaScript #3 — 範疇(Scope)、暫時死區(TDZ)
>[參考資料](https://medium.com/@realdennis/%E9%96%92%E8%81%8A-var%E8%88%87let%E7%9A%84%E6%87%B6%E4%BA%BA%E5%8C%85-javascript-b5a3f40ee28d/) 用 1 分鐘簡單地了解 — JavaScript中 var 與 let 的主要差別
>[參考資料](https://wcc723.github.io/javascript/2017/12/20/javascript-es6-let-const/) ES6 開始的新生活 let, const
**不同點 1: ==作用域==**
var、let、const 三者的變數作用範圍:
<font color="0a97b0">**var:function scope**</font>
<font color="0a97b0">**let、const:block scope {}**</font>
```javascript=
// ES6 syntax
for(let i = 0; i < 5; i++) {
console.log(i); // 0,1,2,3,4
}
console.log(i); // undefined 作用域僅限於塊 {}
================================================
// ES5 syntax
for(var i = 0; i < 5; i++) {
console.log(i); // 0,1,2,3,4
}
console.log(i); // 0,1,2,3,4,5
```
```javascript=
function varMing () {
var ming = '小明';
if (true) {
var ming = '杰哥';
// 這裡的 ming 和if外的ming指向同一個記憶體盒子
// 重新賦值後ming的值被更新為'杰哥'
}
console.log(ming); // '杰哥'
}
varMing();// '杰哥'
======================================================
function letMing () {
let ming = '小明';
if (true) {
let ming = '杰哥';
// 這裡的 ming 是不同的,只有在這個 if block { } 才有作用
}
console.log(ming); // '小明'
}
letMing();// '小明'
```
**不同點2:==在同個區塊 { } 上 var 可以重複宣告,但 let /const 會出錯==**
###### `重複宣告的差異`
```javascript=
{
let medium = 'good!';
...
let medium = 20;
//SyntaxError: Identifier 'medium' has already been declared
}
================v.s================
{
var already = 'no';
var already = 'yes';
console.log(already); //yes
}
```
(let 不能重複宣告變數,==但可以重新賦值(使用=指定運算子))==
const 宣告變數後 ==不可以使用指定(賦值)運算子 = 重新賦值==
```javascript=
var x = 1
console.log(x) // 1
x = 5 //使用=指定運算子 重新賦值
console.log(x) // 5
let y = 2
console.log(y) // 2
y = 10 //使用=指定運算子 重新賦值
console.log(y) // 10
const z = 1
z = 3 //TypeError: Assignment to constant variable.
```
**不同點3: ==var 跟 let / const hoisting 的表現不同==**
>[參考資料](https://ithelp.ithome.com.tw/articles/10213188) ES6 小筆記】變數宣告 - let、const 哪裡好?跟 var 說掰掰
:::
### <font color="ea907a">**const**</font>
>[參考資料](http://www.tastones.com/zh-tw/tutorial/javascript/javascript-es6-features/) JavaScript ES6 功能
const針對是常數的定義,==常數在一宣告時就必定要指定給值==,不然會產生錯誤。
如果你宣告的常數是一個==物件或陣列類型==,像這種參照類型的值,==裡面的值是可以作改變的。==
```javascript=
// Changing object property value
const PERSON = {name: "Peter", age: 28};
console.log(PERSON.age); // 28
PERSON.age = 30;
console.log(PERSON.age); // 30
// Changing array element
const COLORS = ["red", "green", "blue"];
console.log(COLORS[0]); // red
COLORS[0] = "yellow";
console.log(COLORS[0]); // yellow
```
![](https://i.imgur.com/sbcG2FY.png)
:::warning
>[參考資料](https://w3c.hexschool.com/blog/530adff5) ECMAScript6 入門:var、let、const 差異
當 `const`被宣告為物件、常數時,可以加上==freeze==方法來凍結。
```javascript=
const obj = {
url: 'http://wualnz.com'
}
obj.url = 'http://helloWorld.com'
```
![](https://i.imgur.com/mVAwOvn.png)
`obj.url`重新定義為`http://helloWorld.com`時,成功被修改了。
當使用陣列、或物件時,有沒有什麼辦法不被修改?
有,使用 `freeze`(凍結)
```javascript=
const obj = {
url: 'http://wualnz.com'
}
Object.freeze(obj)
obj.url = 'http://helloWorld.com'
```
![](https://i.imgur.com/YzSPmnp.png)
當加上`Object.freeze(obj)`後,便無法再更改`obj.url`了
:::
### <font color="ea907a">**let**</font>
>[參考資料](https://kuro.tw/posts/2019/02/23/%E8%AB%87%E8%AB%87-JavaScript-%E7%9A%84-setTimeout-%E8%88%87-setInterval/) 談談 JavaScript 的 setTimeout 與 setInterval
**for圓括號中的let變數仍然是在區塊作用域**
由於區塊作用域造成的結果,在==每次的for迴圈執行時==,用==let宣告的變數都會重新綁定(re-bind)一次==。這是在for語句中的var與let的差異
###### `var 會直接將 i 宣告成全域變數,不斷透過 for 迴圈累加,在 setTimeout 實際執行時只會拿到 10 這個數字。`
###### ` setTimeout (單位為毫秒) `
```javascript=
for (var i = 0; i < 10; i++) {
console.log(i);
setTimeout(function () {
console.log('這執行第' + i + '次');
}, 1000);
}
```
###### `console.log() 會在「一秒鐘之後」同時印出「十次 這執行第 10 次」`
###### `由於 JavaScript 切分變數有效範圍 (scope) 的最小單位為 function,所以當 1000ms 過去` ==`變數 i 的值早已是 for 迴圈更新完畢的 i ,而不是迴圈內當下的那個 i`==
![](https://i.imgur.com/tfpP7xE.png)
###### `let 是屬於 block {} 變數`
```javascript=
for (let i = 0; i < 10; i++) {
console.log(i);
setTimeout(function () {
console.log('這執行第' + i + '次');
}, 1000);
}
```
![](https://i.imgur.com/SzffiuE.png)
>[參考資料](https://wcc723.github.io/javascript/2017/12/20/javascript-es6-let-const/) ES6 開始的新生活 let, const
>[參考資料](https://anthonychao.site/article/2019-12-05-let_const_var/) let, const 跟 var 的比較跟應用
---
## Template Literals 模板字串符
>[參考資料](https://medium.com/@realdennis/javascript-%E8%A8%AD%E8%A8%88%E4%B8%80%E5%80%8B%E6%8E%A5%E5%8F%97%E6%A8%A1%E6%9D%BF%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%87%BD%E6%95%B8-20f2ce452c4e) 不用括號也能呼叫? 設計一個接受模板字符串的函數吧! JavaScript
模板字串符(template literal)是 ES6 中新增的一個相當方便實用的功能,==取代以往在 JS 中用 " " 或 ' ' 及 + 輸出字串與變數的功能==
語法就是使用==反引號包起來== ,==變數使用 ${ } 包起來==即可
###### 反引號如下
``` js
` `
```
可以很輕易的做到
<font color="ea907a">**輸出多行文字(字串需要換行)**</font>
<font color="ea907a">**字串中插入變數**</font>
<font color="ea907a">**字串中使用方法、函式**</font>
###### 範例一
```javascript=
var father = {name:'Dio',age:100};
var friend = {name:'Mista',age:19}
// 以前字串是這樣
console.log('我的爸爸叫做' + father.name + ',我的朋友叫做'+ friend.name);
// 模板字符串允許你這麼做:
console.log(`我的爸爸叫做${father.name},我的朋友叫做 ${friend.name}`);
```
![](https://i.imgur.com/bkLy0Lv.png)
###### 範例二
![](https://i.imgur.com/5G0XhDP.png)
![](https://i.imgur.com/Ln3N4Nu.png)
>[參考資料](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Template_literals#%E6%A8%99%E7%B1%A4%E6%A8%A3%E6%9D%BF%E5%AD%97%E9%9D%A2%E5%80%BC) MDN
---
## Destructuring 解構
>[參考資料](https://learningsky.io/destructuring-assignment/) 【 JavaScript ES6 】解構賦值
解構賦值==可以用在陣列或物件==,可以提取特定的值成獨立變數。
#### Array Destructuring ==陣列的解構賦值==
###### `原始寫法`
```javascript=
const nums = [1, 2, 3]
const first = nums[0]
const second = nums[1]
const third = nums[2]
console.log(`first: ${first}, second: ${second}, third: ${third}`)
```
![](https://i.imgur.com/n6ns4LU.png)
###### `解構寫法`
```javascript=
const nums = [1, 2, 3]
const [first, second, third] = nums
console.log(`first: ${first}, second: ${second}, third: ${third}`)
```
![](https://i.imgur.com/n6ns4LU.png)
###### `陣列解構設預設值`
```javascript=
const nums = [1, 2, 3]
const [first, second, third, fourth = 5] = nums
console.log(`first: ${first}, second: ${second}, third: ${third}, fourth: ${fourth}`)
```
![](https://i.imgur.com/QYr3QEx.png)
###### `陣列解構忽略元素`
透過`,` 來==忽略陣列元素==
```javascript=
const nums = [1, 2, 3, 5, 6]
const [, second, , , five] = nums
console.log(`second: ${second}, five: ${five}`)
```
![](https://i.imgur.com/NkYYbYz.png)
###### `剩餘部份變成另一個陣列元素`
透過 `...` 將原始陣列==最後的剩餘部份變為另一個陣列元素==
```javascript=
const nums = [1, 2, 3]
const [first, ...others] = nums
console.log(`first: ${first}, others: ${others}`)
```
![](https://i.imgur.com/IRl2Tau.png)
#### 互換數值
###### `原始寫法`
```javascript=
let a = 10
let b = 24
console.log(`a: ${a}, b: ${b}`);
let tmp = a
a = b
b = tmp
console.log(`a: ${a}, b: ${b}`)
```
![](https://i.imgur.com/QPJzkRv.png)
###### `改良寫法`
可直接==將變數值當成 Key 來使用==
```javascript=
let a = 10
let b = 24
console.log(`a: ${a}, b: ${b}`);
[b, a] = [a, b]
console.log(`a: ${a}, b: ${b}`)
```
![](https://i.imgur.com/QPJzkRv.png)
#### 陣列與迴圈
###### `解構`
透過==迴圈方式依序取出陣列中各數值==再使用==陣列解構來取得各數值中的 firstName 、 lastName 與 isEmployee==
```javascript=
const usersInfo = [
['Renee', 'Li', true],
['Jen', 'Chen', false],
]
for (const [firstName, lastName, isEmployee] of usersInfo) {
console.log(`firstName: ${firstName}, lastName: ${lastName}, isEmployee: ${isEmployee}`)
}
```
![](https://i.imgur.com/8snB02e.png)
#### ==物件解構==
###### `原始寫法`
```javascript=
const point = {
x: 10,
y: 24
}
const x = point.x
const y = point['y']
console.log(`x: ${x}, y: ${y}`)
```
![](https://i.imgur.com/krOTxpE.png)
###### `解構寫法`
解構==取物件的 Key==
```javascript=
const point = {
x: 10,
y: 24
}
const { x, y } = point
console.log(`x: ${x}, y: ${y}`)
```
![](https://i.imgur.com/krOTxpE.png)
#### 物件解構設預設值
使用==物件解構並設定初值==
```javascript=
const point = {
x: 10,
y: 24
}
const { x, y, z = 168 } = point
console.log(`x: ${x}, y: ${y}, z: ${z}`)
```
![](https://i.imgur.com/cn5KAWY.png)
###### `物件中包含另一個物件`
```javascript=
const myObject = {
props: {
match: 'Hello World'
}
}
const {
props: {
match
},
} = myObject
console.log(match)
```
![](https://i.imgur.com/0wP3y9h.png)
###### `物件解構指定新名稱`
==取出物件中對應的 Key 值後再將此 Key 重新名命為 : 之後的名稱==
```javascript=
const point = {
x: 10,
y: 24
}
const { x: poinxX, y: poinxY, z = 168 } = point
console.log(`poinxX: ${poinxX}, poinxY: ${poinxY}, z: ${z}`)
```
![](https://i.imgur.com/1oJnPxs.png)
#### 解構函式參數
###### `原始寫法`
```javascript=
function computeArea(side) {
const { length, width } = side
return length * width
}
console.log(`面積為: ${computeArea({ length: 10, width: 24 })}`)
```
![](https://i.imgur.com/lXLGc7L.png)
###### `解構寫法`
函式參數==透過物件解構取得對應的 Key 值==
```javascript=
function computeArea({ length, width }) {
return length * width
}
console.log(`面積為: ${computeArea({ length: 10, width: 24 })}`)
```
![](https://i.imgur.com/lXLGc7L.png)
#### 物件與迴圈
###### `解構`
透過==迴圈方式依序取出陣列中各數值==再使用==物件解構來取得各數值中的 firstName 、 lastName 與 isEmployee==
```javascript=
const usersInfo = [
{ firstName: 'Tom', lastName: 'Li', isEmployee: true },
{ firstName: 'Andy', lastName: 'Wei', isEmployee: false }
]
for (const { firstName, lastName, isEmployee } of usersInfo) {
console.log(`firstName: ${firstName}, lastName: ${lastName}, isEmployee: ${isEmployee}`)
}
```
![](https://i.imgur.com/9hAupyE.png)
>[參考資料](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/destructuring.html)解構賦值
## Spread Operator 展開運算子
>[參考資料](https://pjchender.blogspot.com/search/label/es6) 展開運算子
==展開運算子(Spread Operator)與其餘參數(Rest parameters)== 是ECMAScript 6中的其中一種新特性
語法的內容:
<font color="ea907a">**符號是三個點(...)**</font>
<font color="ea907a">**都與陣列有關**</font>
**展開運算子**的 `... `後面必定是==接一個陣列或物件==
###### `基本用法`
```javascript=
//陣列
let number = [1,2,3,4,5];
console.log(...number); // 1,2,3,4,5
```
![](https://i.imgur.com/X9rsi8E.png)
```javascript=
//字串
let str = 'kanboo'
console.log(...str); // "k","a","n","b","o","o"
```
![](https://i.imgur.com/2FZHVa2.png)
###### `將二個Array合併(新舊寫法比較)`
```javascript=
//===========過去寫法===========
let groupA = ['爸爸', '媽媽'];
let groupB = ['老大','老二','老么'];
const groupAll = groupA.concat(groupB);
console.log(groupAll);
// ["爸爸", "媽媽", "老大", "老二", "老么"];
```
![](https://i.imgur.com/FpStOKk.png)
```javascript=
//===========新的寫法===========
let groupA = ['爸爸', '媽媽'];
let groupB = ['老大','老二','老么'];
const groupAll = [...groupA, ...groupB]; //拆解完後,再用陣列[]包起來,產生新的陣列
console.log(groupAll);
// ["爸爸", "媽媽", "老大", "老二", "老么"];
```
![](https://i.imgur.com/FpStOKk.png)
也可以用來==把陣列展開,傳入函式之中==,例如下面加總函式的範例:
###### `將 陣列展開 傳入函式`
```javascript=
function sum(a, b, c) {
return a + b + c;
}
var args = [1, 2, 3];
console.log(sum(...args)); // 6
```
![](https://i.imgur.com/vfXaw37.png)
###### `淺層複製`
陣列與物件相同都有著傳參考的特性,所以當把==陣列賦予到另一個值上==時,==修改其中一個另一個也會跟著變動==。
###### 傳址:更動groupB 會 影響groupA
```javascript=
// 由於傳參考的關係,所以將一個陣列傳到另一個上時
// 兩個的值其實是一樣的
let groupA = ['老大','老二','老么'];
let groupB = groupA;
groupB.push('小花');
//輸出
console.log(groupA); // ['老大','老二','老么','小花'];
console.log(groupB); // ['老大','老二','老么','小花'];
```
![](https://i.imgur.com/kBnhStl.png)
###### 展開運算子 它是一個一個將值寫入,所以他也有`淺層的複製(shallow copy)` 。
###### 淺層複製:更動groupB 不會 影響groupA
```javascript=
// 這個屬於淺拷貝,所以不會影響到另一個物件
let groupA = ['老大','老二','老么'];
let groupB = [...groupA];
groupB.push('小花');
//輸出
console.log(groupA); // ['老大','老二','老么'];
console.log(groupB); // ['老大','老二','老么','小花'];
```
![](https://i.imgur.com/78Hp1f1.png)
###### `範例`
``` js
// 同樣道理,arguments 不是真正的陣列,也可以透過 ... 來轉成純陣列
var originCash = 1000;
function updateEasyCard() {
let arg = [...arguments]
let sum = arg.reduce(function (accumulator, currentValue) {
// 分別為前一個回傳值, 當前值
return accumulator + currentValue; // 與前一個值相加
}, 0);
// 如果使用 arguments 則會出現 `arguments.reduce is not a function`
console.log('我有 ' + sum + ' 元');
}
updateEasyCard(0); // 我有 0 元
// arguments = [];
updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500); // 我有 718 元
// arguments = [10, 50, 100, 50, 5, 1, 1, 1, 500];
```
![](https://i.imgur.com/9lx9LmA.png)
>[參考資料](https://wcc723.github.io/javascript/2017/12/24/javascript-spread-operator/) JavaScript 展開與其餘
### ==其餘參數(Rest Operator)==
將一個不確定數量的參數==集合在一個陣列中==
###### `範例1`
可傳入不固定的參數,1個 or 多個 皆可..
```javascript=
function sum(...numbers) {
var result = 0;
numbers.forEach(function (number) {
result += number;
});
return result;
}
//傳入一個值
console.log(sum(1)); // 1
//傳入多個值
console.log(sum(1, 2, 3, 4, 5)); // 15
```
![](https://i.imgur.com/0nusjtk.png)
###### `範例2`
如果function有先定義別的參數,就會將傳入的參數值先給定義好的參數,剩下的就全部塞入其餘參數。
```javascript=
function restArray(x, y, ...others) {
console.log("x",x); // x: 1
console.log("y",y); // y: 2
console.log("others",others); // others: [3, 4, 5]
}
//拆解陣列
restArray(1, 2, 3, 4, 5);
```
![](https://i.imgur.com/7bMzPoZ.png)
其餘參數(Rest parameters)有一個限制,**就是這個參數一定是==函式的「最後一個」==。**
你如果放在其餘的參數前,就會==產生錯誤==。
###### `反過來寫就會Error`
```javascript=
function restArray(...others, x, y) {
console.log("x",x);
console.log("y",y);
console.log("others",others);
}
//拆解陣列
restArray(1, 2, 3, 4, 5); //error SyntaxError: Rest parameter must be last formal parameter
```
![](https://i.imgur.com/I0W7TXh.png)
>[參考資料](https://kanboo.github.io/2018/01/26/ES6-SpreadOperator-RestOperator/) ES6-展開運算子(Spread Operator)、其餘參數(Rest Operator)
## `Arrow Function` 箭頭函式
>[參考資料](https://kanboo.github.io/2018/01/23/ES6-Arrowfunctions/) ES6-箭頭函式 (Arrow functions)
簡短的語法
一般使用==箭頭函式==與 function 的用法大致一致,可以傳入參數、也有大括號包起來,除此之外箭頭函式也有更簡短的寫法如下:
```javascript=
// 正常寫法
var callSomeone = (someone) => {
return someone + '你好嗎?'
}
console.log(callSomeone('hello'))
// 縮寫,單一行陳述不需要 {}
var callSomeone = (someone) => someone + '感謝~'
console.log(callSomeone('衷心'))
// 只有一個參數可以不加括號
var callSomeone = someone => someone + '再見!'
console.log(callSomeone('珍重'))
// 沒有參數時,一定要有括號
var callSomeone = () => '期待' + '再相逢Q'
console.log(callSomeone('期待'))
```
![](https://i.imgur.com/Xlwnr9v.png)
上述有個小地方也要注意一下,在大括號內的 `{}` 是需要==自行加入 return,如果沒有傳入值則會出現 undefined==。
```javascript=
var callSomeone = (someone) => { someone + '我很好ww' }
console.log(callSomeone('hello')) // undefined
```
![](https://i.imgur.com/YgesmkN.png)
### 綁定的 this 不同
>[參考資料](https://blog.niclin.tw/2019/09/30/arrow-function-in-javascript/) 箭頭函式 (Arrow functions)
:::warning
``` js
* this 是被綁定的,apply, call, bind 在 Arrow function 中是無法改變 this 的
* 不能用在 constructor因為, this 是在物件下建立的
* 沒有一般函式有的隱藏arguments物件。
* 箭頭函式不能當作 generators 使用,使用yield會產生錯誤。
```
:::
```javascript=
// 普通寫法
const currentLanguage = (user) => {
return user.locale
}
// 縮寫,還幫你寫好 return
const currentLanguage = (user) => user.locale
// 一個參數時可以不加 () 括號
const currentLanguage = user => user.locale
// 沒參數時一定要有 () 括號
const currentLanguage = () => "zh-TW"
// 寫大括號時一定要有 return
const currentLanguage = user => { return user.locale }
```
```javascript=
let str = [
'Hello',
'Johnson',
'How are you?',
'Fine, thank you'
];
// Function
console.log(str.map(function (obj) {
return obj.length;
}));
// [ 5, 7, 12, 15 ]
//===================>>
// Arrow function
console.log(str.map(str => str.length));
// [ 5, 7, 12, 15 ]
```
![](https://i.imgur.com/lrCGv18.png)
### 沒有 arguments 參數
箭頭函數裡沒有argument物件,可使用 其餘參數(Rest Operator) 替代
```javascript=
const other = (...others) => others;
console.log(other(10, 20, 30, 40, 50)) // [10, 20, 30, 40, 50]
```
### apply, call, bind 無效
this 在 Arrow function 中是被綁定的,所以套用 apply, call, bind 的方法時是無法修改 this。
>[參考資料](https://blog.techbridge.cc/2019/02/23/javascript-this/) 淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
---
## ES6模組的輸出與輸入
>[參考資料](https://blog.typeart.cc/%E6%B7%BA%E8%AB%87JavaScript%20ES6%E7%9A%84import%E8%88%87import%7B%7D%E5%8F%8Aexport%E5%8F%8Aexport%20default%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F/) 淺談JavaScript ES6的import與import{}及export及export default使用方式
### 多個輸出名稱
模組輸出可以使用==export==關鍵字,在想要輸出(也就是變為公開部份)加在前面,物件、類別、函式與原始資料(變數與常數)都可以輸出,例如以下的範例:
```javascript=
export const aString = 'test'
export function aFunction(){
console.log('function test')
}
export const aObject = {a: 1}
export class aClass {
constructor(name, age){
this.name = name
this.age = age
}
}
```
上面稱之為多個輸出名稱的情況,有兩種方式可以進行輸入,一種是每個要輸入的名稱都需要定在在花括號(=={}==)之中,例如以下的範例:
```javascript=
import {aString, aObject, aFunction, aClass} from './lib.js'
console.log(aString)
console.log(aObject)
```
另一種是使用萬用字元(==*==),代表要輸入所有的輸出定義的值,不過你==需要加上一個模組名稱==,例如下面程式碼中的myModule,這是為了防止命名空間的衝突之用的,之後的程式碼中都需要用這個模組名稱來存取輸出模組中的值,這個作法不常使用:
```javascript=
import * as myModule from './lib.js'
console.log(myModule.aString)
console.log(myModule.aObject)
myModule.aFunction()
const newObj = new myModule.aClass('Inori', 16)
console.log(newObj)
```
### 單一輸出名稱
這個要輸出成為模組的程式碼檔案中,只會有一個輸出的變數/常數、函式、類別或物件,通常會加上==default==關鍵詞。如果要使用有回傳值的函式,通常也是用單一輸出的方式。例如以下的範例:
```javascript=
function aFunction(param){
return param * param
}
export default aFunction
```
對單一輸出的模組就不需要用花括號,這代表只輸入以default值定義的輸出語句:
```javascript=
import aFunction from './lib2.js'
console.log(aFunction(5))
```
這是最特別的,可以在輸入時改變輸入值的名稱,這樣可以讓作輸入檔案中,確保不會有名稱衝突的情況:
```javascript=
import square from './lib2.js'
console.log(square(5))
```
### 輸出語法
```javascript=
export var x = 42; // export a named variable
export function foo() {}; // export a named function
export default 42; // export the default export
export default function foo() {}; // export the default export as a function
export { encrypt }; // export an existing variable
export { decrypt as dec }; // export a variable as a new name
export { encrypt as en } from 'crypto'; // export an export from another module
export * from 'crypto'; // export all exports from another module
```
### 輸入語法
```javascript=
import 'jquery'; // import a module without any import bindings
import $ from 'jquery'; // import the default export of a module
import { $ } from 'jquery'; // import a named export of a module
import { $ as jQuery } from 'jquery'; // import a named export to a different name
import * as crypto from 'crypto'; // import an entire module instance object
```
### `export` vs `export default`
最大的差別就是:同一份js檔案,==export可以有無限多個==,==export default只能有一個==!
**使用default的話,你得把要export的所有東西寫進一個{}裡面**
```javascript=
export const a = 123;
export const myFunc = ()=>{console.log('this is myFunc')}
//...可以有一大堆export
//------上面是export,下面是export default的分隔線------
const test = () => '這個test function要從default匯出的';
export default {
b: 'b',
test,
test2: () => 'test2 function'
}
```
你也可以在一份文件裡同時使用export與export default
### 為什麼還要有default呢?
主要是在另一份js檔要import時是否需要寫`{}`
==若是用`export default`,在別的js檔import時不必`{}`==
### `import vs import {}`
**==import中需不需要寫{},則是看引入的文件是否有使用到default==**
---
## [Babel](https://babeljs.io/)
>[參考資料](https://medium.com/i-am-mike/webpack%E6%95%99%E5%AD%B8-%E5%9B%9B-javascript-%E8%88%87-babel-1d7acd911e63) JavaScript 與 Babel
Babel 是一個 ==JavaScript 的轉譯器==,可以幫你==轉成需要的版本==,意思是你依舊可以使用潮潮的最新語法,而不用為了使用者環境而吐血。
###### 安裝指令
```javascript=
npm install babel-loader @babel/core @babel/preset-env --save-dev
```
安裝好了後來看看 `package.json`
```json=
{
"name": "Babel",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"watch": "webpack --mode development --watch",
"start": "webpack --mode development",
"deploy": "webpack --mode production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-loader": "^8.0.2",
"webpack": "^4.21.0",
"webpack-cli": "^3.1.2"
}
}
```
在Script裡面有3個指令
* watch : 執行編譯然後不中斷,設定成 development 版本。
* start : 執行一次性編譯,設定成 development 版本。
* deploy : 執行一次性編譯,設定成 production 版本。
#### 安裝的工具裡面也安裝了babel
* `babel-loader `:webpack要去讀取任何檔案格式都需要靠loader這個工具去做判讀,然後再去做轉換,所以我們就會需要webpack掛載這個babel-loader。
* `@babel/core`: 程式需要調用Babel的API進行編譯。
* `@babel/preset-env`:可以使用最新版本的JavaScript然後去編譯,不用去理會哪些語法需要轉換。
:::warning
Babel 不只轉換新版本的JavaScript,也可以轉換React 的 jsx 還有TypeScript等等
:::
[參考資料](https://medium.com/i-am-mike/webpack%E6%95%99%E5%AD%B8-%E5%9B%9B-javascript-%E8%88%87-babel-1d7acd911e63)