點燈坊

失くすものさえない今が強くなるチャンスよ

使用 objLength() 取得 Object 的大小

Sam Xiao's Avatar 2019-10-22

ECMAScript 對 Array 提供了 length() 讓我們獲得 Array 的大小;但對於 Object 的 Length,ECMAScript 並沒有提供直接方法,必須使用較 Tricky 方式。

Version

macOS Catalina 10.15
VS Code 1.39.2
Quokka 1.0.256
ECMAScript 2017
Ramda 0.26.1
Wink-fp 0.1.22

Object.keys()

let data = {
  firstName: 'Sam',
  lastName: 'Xiao'
};

let objLength = obj => Object.keys(obj).length;

objLength(data); // ?

所謂 object 的 length,其實就是 property 個數,ECMAScript 並沒有提供直接方式取得,但 array 有 length property。

所以先使用 Object.keys() 將 key 部分變成 array,就可以使用 array.length 求得。

objsize000

Object.values()

let data = {
  firstName: 'Sam',
  lastName: 'Xiao'
};

let objLength = obj => Object.values(obj).length;

objLength(data); // ?

既然能用 Object.keys(),當然也能用 Object.values()

objsize001

Object.entries()

let data = {
  firstName: 'Sam',
  lastName: 'Xiao'
};

let objLength = obj => Object.entries(obj).length;

objLength(data); // ?

既然 Object.keys()Object.values() 都能用,當然也能使用 ES2017 的 Object.entries()

objsize002

Pipeline

import { pipe, keys, length } from 'ramda';

let data = {
  firstName: 'Sam',
  lastName: 'Xiao'
};

let objLength = pipe(keys, length);

objLength(data); // ?

由以上寫法可發現資料先經過 Object.keys() 處理,再將結果傳給 Array.prototype.length ,事實上是一個 pipeline 過程,可用 pipe()keys()length() 整個流程串起來,也順便 point-free。

keys() 相當於 Object.keys() 的 function 版本;而 length() 相當於 Array.prototype.length 的 function 版本。

objsize004

Function Composition

import { compose, keys, length } from 'ramda';

let data = {
  firstName: 'Sam',
  lastName: 'Xiao'
};

let objLength = compose(length, keys);

objLength(data); // ?

pipe() 是以 data 思考,若以 funciton 思考,就是將所有參與 pipeline 的 function 組合起來,也就是 function composition。

使用 compose()keys()length() 組合起來,也因為是組合 function,故與 argument 無關,因此自然 point-free。

objsize003

Wink-fp

import { objLength } from 'wink-fp';

let data = {
  firstName: 'Sam',
  lastName: 'Xiao'
};

objLength(data); // ?

Wink-fp 已內建 objLength(),可直接使用。

objLength()
[a] -> Number
取得 Object 的大小

[a]:data 為 array
Number:回傳 object 的大小,也就是 property 個數

objsize005

Conclusion

  • Ramda 亦提供 values(),相當於 Object.values(),因此也能組合 values()length()
  • Array.length 為 property,因此無法 function composition
  • OOP 與 FP 雖然功能相同,但因為提供方式不同,使用方式與觀念就相差很大
  • compose()pipe() 為一體兩面,若無法由 imperative 一步到位想到 function composition,可先由 imperative 重構成 pipeline,再由 pipeline 重構成 function composition

Reference

MDN, Object.keys()
MDN, Object.values()
MDN, Object.entries()
Ramda, keys()
Ramda, values()
Ramda, length()
Ramda, pipe()
Ramda, compose()