ES6(Default Parameters、箭頭函式、Import 與 Export、Babel)


Posted by saffran on 2021-02-05

加上預設值:Default Parameters

default parameters 就是「預設值」的意思

「function」搭配預設值來使用

這裡是一個 repeat 函式

function repeat(str, times){
  return str.repeat(times)
}

console.log(repeat('love', 5))
// output: lovelovelovelovelove

在呼叫 repeat 函式時,如果參數 times 沒有寫,那麼參數 times 就會是 undefined,然後印出 repeat('love') 的結果也會是什麼都沒有

function repeat(str, times){
  console.log(times) // 把 times 印出來看看
  return str.repeat(times)
}

console.log(repeat('love'))

output:

undefined

設定參數的預設值

repeat 函式的參數 times 後方設定 = 5 的預設值,這樣,在呼叫 repeat 函式時如果沒有傳入 timestimes 就會是預設值(5)

function repeat(str, times = 5){
  console.log(times) // 把 times 印出來看看
  return str.repeat(times)
}

console.log(repeat('love'))

output:

5
lovelovelovelovelove

也可以把兩個參數 strtimes 都設定預設值
這樣,在呼叫 repeat 函式時,如果完全沒有傳入參數,就會都使用預設值

function repeat(str = 'hey', times = 3){
  return str.repeat(times)
}

console.log(repeat())
// output: heyheyhey

「解構」搭配預設值來使用

「預設值」也可以用在陣列、物件的解構

const obj = {
  a: 8,
  b: 9
}

const {a, b} = obj

console.log(a, b)
// output: 8 9

如果在宣告變數 obj 時,就沒有 a,那麼解構之後印出變數 a 就會是 undefined

const obj = {
  b: 9
}

const {a, b} = obj

console.log(a, b)
// output: undefined 9

設定變數的預設值

在解構時,可以幫變數 a 設定預設值 = 333
在宣告變數 obj 時,如果沒有 a,那麼印出來的變數 a就會是 333

const obj = {
  b: 9
}

const {a = 333, b} = obj // 幫變數 a 設定預設值

console.log(a, b)
// output: 333 9

但在宣告變數 obj 時,如果有 a,就不會使用預設值了

const obj = {
  a: 20
}

const {a = 333, b = 'lemon'} = obj // 幫變數 a 設定預設值

console.log(a, b)
// output: 20 lemon

宣告 Function 的新方式:箭頭函式 Arrow Function

在 ES5,宣告 function 的方式有兩種:

  • 第一種
    function test(n){
    return n * 2
    }
    
  • 第二種
    const test = function(n){
    return n * 2
    }
    

箭頭函式

在 ES6,有另一種宣告 function 的方式,也就是上方第二種的變化版:

省略 function 這個關鍵字

  • 把 function 這個關鍵字省略
  • (n) 後面加上一個箭頭符號 =>
const test = (n) => {
  return n * 2
}

省略參數的小括號

  • 如果只有傳入一個參數的話,參數的小括號可以省略掉
    const test = n => {
    return n * 2
    }
    

省略大括號、return

  • 如果在大括號內的程式碼只有要「return 一行」的話,就可以省略大括號和 return 這個關鍵字
    const test = n => n * 2
    
    如果想要把大括號加回去,記得也要把 return 加回去,不然 function 預設都會 return undefined

    可參考 箭頭函式出現 bug 的可能原因

箭頭函式的好處

使用箭頭函式的好處是:程式碼更簡潔、可讀性更高,尤其是在使用array 相關的 function 時更明顯

例如:
在使用 filter()map() 時,裡面都要傳入一個 function
ES5 的寫法是這樣:

let arr = [4, 5, 6, 7, 8]

console.log(
  arr
  .filter(function(value){
    return value > 4
  })
  .map(function(value){
    return value * 2
  })
)
// output: [ 10, 12, 14, 16 ]

ES6 的寫法是這樣:

  • 省略 function 這個關鍵字
  • 省略參數的小括號
  • 如果在大括號內的程式碼只有一行的話,就可以省略大括號和 return 這個關鍵字
let arr = [4, 5, 6, 7, 8]

console.log(
  arr
    .filter(value => value > 4)
    .map(value => value * 2)
)
// output: [ 10, 12, 14, 16 ]

Import 與 Export

關於 module 的輸出、引入,在 ES5 和 ES6 有什麼不一樣呢?

先複習一下 ES5 的輸出、引入

在 ES5,module.exportsrequire 是「成對使用」的

我現在有兩個檔案,分別是:index.js 和 utils.js

輸出 module.exports

在 utils.js 把 module 輸出

function add(a, b){
  return a + b
}

module.exports = add

引入 require

然後在 index.js 把 module 引入

let myModule = require('./utils')

console.log(myModule(8, 9))
// output: 17

ES6 的輸出、引入

在 ES6,會有不同的語法來輸出、引入 module

是「成對使用」的

輸出 export

export 這個關鍵字可以同時把多個東西輸出

寫法一 export

在 utils.js
假設我想要輸出 add 函式,就在 add 函式前面加上 export這個關鍵字即可

假設我也想要輸出 PI 這個變數,也一樣就在變數最前面加上 export 這個關鍵字即可

export function add(a, b){
  return a + b
}

export const PI = 3.14

寫法二 export{}

在 utils.js
假設我想要輸出 add 函式和 PI 變數,就在下面寫一個 export 加大括號,然後在大括號裡面寫上 add 函式和 PI 變數

注意!這裡的 export {add, PI} 並不是一個物件

function add(a, b){
  return a + b
}

const PI = 3.14

export {
  add,
  PI
}

引入 import { add, PI } from './utils.js'

import { add, PI } from './utils.js'

console.log(add(8, 9), PI)
// output: 17 3.14

如果直接用 node index.js 執行的話,會出現錯誤:它認不得 import 這個東西
原因是:
目前 Node.js 的版本,還沒辦法原生的支援 import 語法

因此,要用 npx babel-node index.js 來執行 index.js

用別的名稱輸出(使用 as 這個關鍵字)

假設,我想要用 addFunction 這個新的名稱來輸出 add 函式

在 utils.js 的 export 使用 add as addFunction

as 這個關鍵字來幫 add 函式取別名
例如說 export { add as addFunction }

function add(a, b){
  return a + b
}

const PI = 3.14

export {
  add as addFunction,
  PI
}

那在 index.js 引入時,就要使用新的名稱 addFunction

import { addFunction, PI } from './utils.js'

console.log(addFunction(8, 9), PI)
// output: 17 3.14

用別的名稱引入(使用 as 這個關鍵字)

在 index.js 的 import 使用 addFunction as plus

在引入時,如果覺得 addFunction 這個名稱太長了,可以使用 as 來取另一個名稱

例如,我把 addFunction 重新取名叫做 plus

import { addFunction as plus, PI } from './utils.js'

console.log(plus(8, 9), PI)
// output: 17 3.14

* 把所有東西一次引入進來(此方法很常用)

utils.js 的輸出:

function add(a, b){
  return a + b
}

const PI = 3.14

export {
  add as addFunction,
  PI
}

在 index.js 引入時,如果不想要把每一個要引入的東西都很明確地寫出來,可以用 * 把 utils.js 裡面的所有東西全部都 import 進來

使用這句 import * as hello from './utils.js' 即可
這句的意思是:
把 utils.js 裡面的所有東西,用 hello 這個 module 名稱(自己隨意取)引入到 index.js 裡面

在程式中,* 通常代表「所有東西」的意思

因此,

  • 要使用 add 函式時,就要用 hello.addFunction(8, 9) 這樣子
  • 要使用 PI 時,就要用 hello.PI 這樣子
import * as hello from './utils.js'

console.log(hello.addFunction(8, 9), hello.PI)
// output: 17 3.14

export default

default 就是「預設值」的意思

在 utils.js 輸出時,

  • add 函式前面加上 export default
  • PI 前面只有寫 export 而已
export default function add(a, b){
  return a + b
}

export const PI = 3.14

輸出時有 default 這個關鍵字,引入就不需要大括號(因為:預設就會引入)

因為 add 函式在輸出時,有加上 default
所以,在 index.js 用 import 引入時,add 不需要加大括號,直接寫上 add 就可以把 add 函式引入了

import add from './utils.js'

console.log(add(8, 9))
// output: 17

輸出時沒有 default 這個關鍵字,引入就需要大括號

因為 PI 在輸出時,沒有加上 default
所以,在 index.js 用 import 引入時,PI 需要加大括號

import add, {PI} from './utils.js'

console.log(add(8, 9), PI)
// output: 17 3.14

default 來預設引入,背後的原理可以看成是這樣:

import {default as add, PI} from './utils.js'

console.log(add(8, 9), PI)

下面這兩句是一樣的意思:

import {default as add} from './utils.js'
import add from './utils.js'

Babel 簡介與基本使用方法

Babel 是現代前端開發中,一個不可或缺的工具

如果我想用某個語法,但目前這個語法在舊的瀏覽器還沒被支援,這時該怎麼辦?

就去開發一個工具,把新語法轉換成舊的語法,讓舊的瀏覽器都可以支援

因為前端的發展速度比「瀏覽器更新的速度」要快很多,因此才會需要這麼多前端工具來解決舊瀏覽器支援度或是其他問題

而 Babel 就是一個這樣的前端工具:
輸入 ES6/ES7/ES8 的語法,經過 Babel 編譯之後,轉換成 ES5(如果是在 IE7/IE8 這種超舊的瀏覽器,甚至會轉換成 ES4)

ES6/ES7/ES8 => Babel => ES4/ES5

假設,專案資料夾的檔案有:

  • utils.js (輸出)
    ```javascript=
    export default function add(a, b){
    return a + b
    }

export const PI = 3.14

* index.js (輸入)
```javascript=
import add from './utils.js'

console.log(add(8, 9))

如果 Node.js 的版本在 13.0 以下,輸入指令 node index.js 去執行的話,就會出現錯誤:它還無法支援 import 這個語法

這時,就需要 Babel 的幫忙了

babel-node

Babel 的用法有很多種,這裡要介紹的是 babel-node

babel-node 的指令跟 node 很像(把它當成 node 來用就好),跟 node 的差別在於:babel-node 可以支援更多新的語法,但 node 不行

注意!因為 babel-node 的效能不太好,所以不要用在 production 上面,babel-node 只適合用在自己個人開發上(自己玩玩的)

如果要把 Babel 用在 production 上的話,可以參考這些範例,通常都會先 compile 完之後,再直接用 node 去執行 compile 完的那些檔案

安裝 @babel/core 和 @babel/node

在專案資料夾底下,輸入指令 npm install --save-dev @babel/core @babel/node 來安裝 @babel/core 和 @babel/node

  • 裝好 @babel/core 和 @babel/node 之後,就可以輸入指令 npx babel-node 來進入「可以輸入程式碼」的模式

這時,當我輸入指令 npx babel-node index.js 來執行 index.js,還是會出現錯誤:無法支援 import 語法

原因是:
Babel 還需要設定一些東西,才能支援這些新的語法

安裝 @babel/preset-env

設定方式是:
輸入指令 npm install --save @babel/preset-env 來安裝 @babel/preset-env
preset 裡面是一些設定,會告訴 Babel 關於語法轉換的事情(要把多新的語法,轉換成多舊的語法)

一定要裝 @babel/preset-env 套件,Babel 才會知道要幫我把 ES6 轉換成 ES5 的語法

這時,當我輸入指令 npx babel-node index.js 來執行 index.js,還是一樣會出現錯誤:無法支援 import 語法

原因是:
我只是安裝了 @babel/preset-env 套件,但我還沒跟 Babel 說「我要使用 @babel/preset-env 這個套件」

要怎麼跟 Babel 說「我要使用 @babel/preset-env 這個套件」呢?作法如下:

  1. 新增一個檔案叫做 .babelrc (會是一個隱藏檔案,要放在專案資料夾的根目錄)
  2. 打開 .babelrc,在裡面寫上:
    {
    "presets": ["@babel/preset-env"]
    }
    

意思就是:我的 preset 要使用的是 @babel/preset-env 這個套件

這時,當我輸入指令 npx babel-node index.js 來執行 index.js,就可以成功執行了

總結一下 babel-node 的設定步驟:

  1. 安裝三個必要套件:npm install --save-dev @babel/core @babel/node @babel/preset-env
  2. 新增 .babelrc 檔案
  3. 在 .babelrc 檔案填入內容,告訴 babel 要用這個 preset:
    {
    "presets": ["@babel/preset-env"]
    }
    
    這樣,就可以用 npx babel-node index.js 來執行了!

更多 ES6 的語法

想查詢更多 ES6 新增的語法,可參考 es6-cheatsheet


#javascript







Related Posts

[C#] 如何透過 EmailMessage 寄代理傳送者郵件 How to send an email on half of another user via EmailMessage

[C#] 如何透過 EmailMessage 寄代理傳送者郵件 How to send an email on half of another user via EmailMessage

React Form: Redux Form vs React Final Form vs Formik and Yup

React Form: Redux Form vs React Final Form vs Formik and Yup

MTR04_1109

MTR04_1109


Comments