iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 2
2

本篇將介紹大量 ES6 語法,
在目前版本 Chrome 與 Node 都是可以執行的,但在舊版瀏覽器可能無法執行,
但在文章中不會詳細敘述他們的差異,
只要的目的是希望大家在之後的文章,不會看不懂文法。

本篇重點

如果以下這段都看得懂,那可以輕鬆看過。

const add = (x, y) => x + y
const sum = (...xs) => {
	let result = 0
	for (let i = 0; i < xs.length; i++) {
		result = add(result, xs[i])
	}
	return result
}

const data = [1, 2, 3, 4, 5, 6, 7, 8]
const total = sum(...data)
console.log({ data, total })

在開始之前

本章的程式碼都是可以在 Console 執行的,為了不要讓變數宣告互相干擾,建議你用 立即函數 (IIFE) ,或在 JS Bin 上執行。

(()=>{
    // 程式碼
})()

Function 是一種物件

究竟 一等公民 (first class) 是什麼意思?
Function 能夠被當作參數傳遞,你可以像對待任何型別一樣對待他,而在 JS 中 Function 被視為一種物件

// ES5

// 宣告一個有名子的函數
function foo1() {}

// 宣告一個匿名函數,並把他指定給 foo2
var foo2 = function() {}

// 你可以把 function 指定給任何人
var foo3 = foo2

// 存進陣列裡
var foos = [foo1, foo2, foo3]

// 當作回傳值
var foo4 = function() {
	return foo1
}

// 當成參數
console.log(foo1)

這些操作在 JS 中是相當常見也相當基本的,稱之為 λ (lambda) ,在 FP 中這個特性是必要的,用以表示一個運算的過程,有著 input 與 output。

Function 的 Function

如何區分是把 Function 當參數傳遞,還是執行他呢?
你只需要注意 Function 後面是否有加上括號,如果有括號,那就是在執行它,當然你也可以藉由其他方式執行 Function ,像是 applycall

var hello = function (x){
    console.log('你好呀!'+x+'!')
}

// 一般的呼叫
hello('JavaScript')

// apply 將傳入兩個變數
// 第一個是 this ,再來是一個 array
// 若第一個參數為 null 或是 undefined,則不會改動 this 的值
hello.apply(null,['JavaScript'])

// call 與 apply 相同
// 不過它不吃 array ,而是 arg1, arg2, ...
hello.call(null,'JavaScript')

Arrow Function

在 JS 的 Syntax 中,用上述的語法宣告一個 function,
function 沒什麼不好,一個小缺點就是它太過攏長了,
為了讓 code 更整潔,我多半會選擇使用 Arrow function
另外為了讓宣告的 function 不會意外被改寫掉,我會選擇用 const 做宣告。

// ES6

// arrow function
const increase1 = x => {
	return x + 1
}

// 若參數只有一個,括號可省略不寫
const increase2 = x => {
	return x + 1
}

// 若馬上就要回傳了,大括號也可省略不寫
const increase3 = x => x + 1

Arrow Function 與 Function 不同的點是 Arrow Function 會自動綁定 this ,而且無法 rebind,如果沒有使用到 this ,那種用法則沒有不同。

對於 JavaScript 中 this 究竟是什麼?
我推薦各位參考這篇 What's THIS in JavaScript ? ,非常非常詳細。
欸這篇文章的作者也是 Kuro 耶! Kuro 太神啦!

Default Parameters

你可以為參數設定初值,這在 ES5 中也是可以辦到的,但 ES6 的語法明顯好看很多。

// ES5
const foo1 = x => {
	x = x || "Javascript"
	console.log(x)
}

// ES6
const foo2 = (x = "JavaScript") => {
	console.log(x)
}

Rest Operator

有時候,Function 接受的參數數量不固定, Rest Operator 會把多的參數併成一個 Array。

const foo = (x, y, ...args) => {
	console.log(x)
	console.log(y)
	console.log(args)
}

foo(1, 2, 3, 4, 5)

// output
// 1
// 2
// [3, 4, 5]

Spread Operator

Spread Operator 用作解構 Array 或 Object,長的跟 Rest Operator 長的很像。

const foo = (x, y, z) => {
	console.log(x)
	console.log(y)
	console.log(z)
}

// ...array2
// 可以看成 array[0], array[1], array[2] ...
let array = [1, 2, 3, 4]
foo(...array)
// 可以看成 foo(array[0], array[1], array[2] ...)

// oupput
// 1
// 2
// 3

Destructuring Assignment

在 ES5 中從 Object 或是 Array 取出值的寫法。

// ES5

var array = [1, 2, 3, 4]
var image = {
	width: 906,
	height: 512,
	src: "//cdn.static03.nicematin.com/media/npo/mobile_xlarge/2016/12/1-trump-1.jpg"
}

var first = array[0]
var second = array[1]

var width = image.width
var height = image.height
var src = image.src
var alt = image.alt || ""

在 ES6 中你可以使用 解構賦值(Destructuring Assignment)
剛剛的 Default ParametersRest Operator 也是可以使用的。

// ES6
let array = [1, 2, 3, 4]
let image = {
	width: 906,
	height: 512,
	src: "//cdn.static03.nicematin.com/media/npo/mobile_xlarge/2016/12/1-trump-1.jpg"
}

let [first, second, ...rest] = array
let { width, height, src, alt = "" } = image

在 Function 中也是可以使用的。

let user = {
	name: "wl0088740",
	birthday: "1996/04/19"
}

const hello = ({ name }) => console.log("Hello! " + name)
hello(user)

Enhanced Object Properties

Enhanced Object Properties 是用來縮短創造 Object 的寫法。

let width = 906
let height = 512
let src =
	"//cdn.static03.nicematin.com/media/npo/mobile_xlarge/2016/12/1-trump-1.jpg"

// ES5
var image = {
	width: width,
	height: height,
	src: src
}

// ES6
let image = { width, height, src }

Template Literals

Template Literals 在串接字串時特別好用,而且可以換行。

let name = "wl00887404"
let birthday = "1996/4/19"

// ES5
console.log(
"Hello, " +	name + "!\nYour birthday is on " + birthday + ".\nHappy Birthday to you!"
)

// ES6
console.log(
`Hello, ${name}!
Your birthday is on ${birthday}.
Happy birthday to you!`
)

看過就忘怎麼辦?

其實各位只要對語法有一點印象就好,需要用的時候,在 ECMAScript 6 — New Features: Overview & Comparison 或是 MDN 都可以找到,並請搭配 Google ,今年鐵人賽也有很多針對 ES6 語法的文章。

後記

在參賽之前,我多次請室友先聽看看,但很常他的心得都是:「你打這些是什麼鬼, JS 可以這樣寫喔?!」
Hmm...,當然可以呀,這是 ES6 的某個 Feature ,但對很多 JavaScript 新手對 ES6 是相當陌生的(或許是因為 w3school 完全沒有提到),其實我對為什麼會有這樣的斷層有很大的疑問。
如果你成功看完整篇文章 (Hooray!) ,你可以捲回本日重點,試試看能不能看懂。
今天很任性的把所有 Syntax 全寫在同一篇,畢竟主題又不是要做 JS 教學,明天來講講一些有 bug 的程式,來從錯誤中學習吧。

參考資料


上一篇
認識 Functional Programming
下一篇
這個 Object 好像怪怪的
系列文
30天快樂學習 Functional Programming14

尚未有邦友留言

立即登入留言