加上預設值: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
函式時如果沒有傳入 times
,times
就會是預設值(5)
function repeat(str, times = 5){
console.log(times) // 把 times 印出來看看
return str.repeat(times)
}
console.log(repeat('love'))
output:
5
lovelovelovelovelove
也可以把兩個參數 str
和 times
都設定預設值
這樣,在呼叫 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 這個關鍵字
如果想要把大括號加回去,記得也要把 return 加回去,不然 function 預設都會 return undefinedconst test = n => n * 2
可參考 箭頭函式出現 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.exports
和 require
是「成對使用」的
我現在有兩個檔案,分別是: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 這個套件」呢?作法如下:
- 新增一個檔案叫做 .babelrc (會是一個隱藏檔案,要放在專案資料夾的根目錄)
- 打開 .babelrc,在裡面寫上:
{ "presets": ["@babel/preset-env"] }
意思就是:我的 preset 要使用的是 @babel/preset-env 這個套件
這時,當我輸入指令 npx babel-node index.js
來執行 index.js,就可以成功執行了
總結一下 babel-node 的設定步驟:
- 安裝三個必要套件:
npm install --save-dev @babel/core @babel/node @babel/preset-env
- 新增 .babelrc 檔案
- 在 .babelrc 檔案填入內容,告訴 babel 要用這個 preset:
這樣,就可以用{ "presets": ["@babel/preset-env"] }
npx babel-node index.js
來執行了!
更多 ES6 的語法
想查詢更多 ES6 新增的語法,可參考 es6-cheatsheet