點燈坊

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

從 Static Method 抽出 Free Function

Sam Xiao's Avatar 2020-07-22

ECMAScript 提供了不少原生 Static Method,但我們也可將其抽成 Free Function 使其更符合 Functional 風格。

Version

macOS Catalina 10.15.6
VS Code 1.47.2
Quokka 1.0.309
ECMAScript 2015
Ramda 0.27.0

Static Method

class Foo {
  static add(x, y) {
    return x + y
  }
}

let { add } = Foo
add(1, 1) // ?

add()Foo class 的 static method,可使用 object destructuring 將 add() 取出成為 free function。

static000

Axios

import axios from 'axios'

axios.get('https://jsonplaceholder.typicode.com/todos/1')
  .then(x => x.data)
  .then(x => x.title) // ?

get()axios 的 static method,因此我們可直接使用 axios.get()

static001

import axios from 'axios'

let { get: ajax } = axios

ajax('https://jsonplaceholder.typicode.com/todos/1')
  .then(x => x.data)
  .then(x => x.title) // ?

既然 get()axios 的 static method,我們就可使用 object destructuring 取出 get(),且順便 alias 成 ajax()

static002

import axios from 'axios'
import { bind } from 'ramda'

let ajax = bind(axios.get, axios)

ajax('https://jsonplaceholder.typicode.com/todos/1')
  .then(x => x.data)
  .then(x => x.title) // ?

另一種方式是改用 Ramda 的 bind() 將 static method 抽成 free function。

static009

Proimse

Promise.resolve(1) // ?

Promise.resolve() 亦為 static method,可建立 Fulfilled Promise。

static003

let { resolve } = Promise

resolve(1) // ?

既然 resolve()Promise 的 static method,理論上我們可使用 object destructuring 將 resolve() 取出成 free function。

static004

但實際執行卻出現錯誤,why not ?

let { resolve } = Promise

resolve.call(Promise, 1) // ?

因為 Promise.resolve() 內部使用了 this,抽成 free function 後,this 就成了 undefined,因此我們必須將 this 找回。

可將 Promise 傳入 .call() 重新定義 this

static005

let { resolve } = Promise

resolve.bind(Promise)(1) // ?

也可將 Promise 傳入 .bind() 回傳新 function。

static006

import { bind } from 'ramda'

let resolve = bind(Promise.resolve, Promise)

resolve(1) // ?

.call().bind() 雖然可行,最後還得傳入 Promise,顯然並不好用。

最簡單方式是使用 Ramda 的 bind()Promise.resolve() 抽成 free function。

static007

Wink-fp

import { resolve } from 'wink-fp'

let f = x => resolve(x)

f(1) // ?

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

static008

Conclusion

  • 只要是內部不使用 this 的 static method,就可以使用 object destructuring 取出 free function
  • 若遇到使用 this static method,雖然可使用 ECMAScript 原生的 .call().bind(),但最萬用的方式是使用 Ramda 的 bind(),無論原 function 是否使用 this 皆可安全抽出 free function

Reference

MDN, Destructuring Assignment
Ramda, bind()