讀取 Object 的 Property 為處理 Object 必備功能,本文整理出 5 種讀取 Property 方式。
Version
macOS Catalina 10.15.4
VS Code 1.43.2
Quokka 1.0.284
ECMAScript 2015
Ramda 0.27.0
Dot Operator
let obj = {
title: 'FP in JavaScript'
}
obj.title // ?
最傳統方式是來自 Java 的 .
讀取 property。
[] Operator
let obj = {
title: 'FP in JavaScript'
}
obj['title'] // ?
ECMAScript 的獨門武器,讓我們可以使用 []
讀取 property。
import { pipe, clone } from 'ramda'
import { stringify } from 'wink-fp'
let obj = {
title: 'FP in JavaScript'
}
let key = 'title'
obj[key] // ?
[]
最大優勢是可以使用 variable,這是 .
所無法的。
Object Destructuring
let obj = {
title: 'FP in JavaScript'
}
let title = obj.title
title // ?
實務上常會定義與 property 相同的 variable 方便後續使用。
import { pipe, clone } from 'ramda'
import { stringify } from 'wink-fp'
let obj = {
title: 'FP in JavaScript'
}
let { title } = obj
title // ?
既然 variable 與 property 名稱相同,在 ES6 可使用 object destructuring 一次解決。
Ramda
import { prop } from 'ramda'
let obj = {
title: 'FP in JavaScript'
}
prop('title')(obj) // ?
以上都是使用 operator 讀取 property,這並不方便 FP 使用,Ramda 提供了 prop()
。
import { propOr } from 'ramda'
let obj = {
title: 'FP in JavaScript'
}
propOr('N/A')('title')(obj) // ?
propOr('N/A')('titled')(obj) // ?
Ramda 另外提供了 propOr()
,若 property 不存在將回傳預設值避免 undefined
的 runtime 錯誤。
import { map, prop } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let f = k => map(prop(k))
f('title')(data) // ?
prop()
的功用在哪呢 ? 它可使 callback 能 point-free,這是 operator 所不能的。
import { prop, map, compose } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let f = compose(map, prop)
f('title')(data) // ?
既然 prop()
是 function,因此可使用 function composition,這也是 operator 所不能的。
Lens
import { lensProp, view } from 'ramda'
let obj = {
title: 'FP in JavaScript'
}
let titleLens = lensProp('title')
view(titleLens)(obj) // ?
FP 會使用 lens 取代 key,藉此達到 immutable。
prop()
是透過 key 讀取 property,view()
則是透過 lens 讀取 property。
import { map, view, lensProp, compose } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let titleLens = lensProp('title')
let f = l => map(view(l))
f(titleLens)(data) // ?
原本 f()
要傳入 key 給 prop()
,現則改傳 lens 給 view()
。
import { map, view, lensProp, compose } from 'ramda'
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
let titleLens = lensProp('title')
let f = compose(map, view)
f(titleLens)(data) // ?
由於 view()
也是 function,因此也可使用 function composition。
Conclusion
- ECMAScript 本身提供了 3 種 operator 讀取 property,唯 operator 適合 imperative,並不適合 FP
- Ramda 提供了
prop()
與view()
讀取 property,唯prop()
要搭配 key,而view()
要使用 lens
Reference
Ramda, prop()
Ramda, propOr()
Ramda, map()
Ramda, compose()
Ramda, lensProp()
Ramda, view()