当我尝试以无点样式编写JavaScript时,我发现如果以这种样式强制执行每个函数,则有时会失去其可读性。例如:

import R from 'ramda'

const ceil = Math.ceil

const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}

// ================= Pointful style ==================
const pageCount = (pagination) => {
  const pages = ceil(pagination.total / pagination.itemsPerPage)
  const remainPages = pagination.total % pagination.itemsPerPage === 0 ? 0 : 1
  return pages + remainPages
}

pageCount(pagination) // => 11

// ================ Pointfree style ==================
const getPages = R.pipe(
  R.converge(R.divide, [R.prop('total'), R.prop('itemsPerPage')]),
  ceil
)

const getRemainPages = R.ifElse(
  R.pipe(
     R.converge(R.modulo, [R.prop('total'), R.prop('itemsPerPage')]),
     R.equals(0)
  ),
  R.always(0),
  R.always(1)
)

const pageCount2 = R.converge(R.add, [
  getPages,
  getRemainPages
])

pageCount2(pagination) // => 11

我编写了一个简单的分页模块,以计算pageCount,以点式和无点式给出总项目数和每页项目数。显然,有指向性的样式比无指向性样式的版本更具可读性。后者有点晦涩难懂。

我做对了吗?有什么方法可以使无点样式的代码更具可读性?

最佳答案

手动撰写

让我们从手动编写函数开始:

const calcPages = (totalItems, itemsPerPage) =>
 ceil(div(totalItems, itemsPerPage));


const div = (x, y) => x / y;

const ceil = Math.ceil;


const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}


console.log(
  calcPages(pagination.total, pagination.itemsPerPage)
);


程序组成

下一步,我们将参数抽象掉:

const comp2 = (f, g) => (x, y) => f(g(x, y));

const div = (x, y) => x / y;

const ceil = Math.ceil;


const calcPages = comp2(ceil, div);


const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}


console.log(
  calcPages(pagination.total, pagination.itemsPerPage)
);


现在,函数定义是无点的。但是调用代码不是。如果您知道高阶函数comp2的工作原理,那么comp2(ceil, div)表达式就非常适合您。

现在很明显,calcPages是错误的名称,因为函数组成更加通用。我们称它为... intDiv(好吧,也许有个更好的名字,但是我很喜欢数学)。

解构修饰符

在下一步中,我们修改intDiv使其可以处理对象:

const destruct2 = (x, y) => f => ({[x]:a, [y]:b}) => f(a, b);

const comp2 = (f, g) => (x, y) => f(g(x, y));

const div = (x, y) => x / y;

const ceil = Math.ceil;


const intDiv = comp2(ceil, div);

const calcPages = destruct2("total", "itemsPerPage") (intDiv);


const pagination = {
  total: 101,
  itemsPerPage: 10,
  currentPage: 1
}


console.log(
  calcPages(pagination)
);


我再次调用了修改后的函数calcPages,因为它现在期望一个特定的pagination对象,因此不太通用。

只要您知道所涉及的高阶函数是如何工作的,则所有内容都是声明性的并且易于阅读,即使它是以无点样式编写的。

结论

无点样式是函数组成,currying和高阶函数的结果。它本身不是一回事。如果您停止使用这些工具以避免无意义的样式,那么您将失去功能编程所提供的很多表现力和优雅。

10-05 21:01
查看更多