Fra*_*ens 7 javascript functional-programming
如何使用ES6在没有任何第三方库的情况下更功能地编写以下代码?
// sample pager array
// * output up to 11 pages
// * the current page in the middle, if page > 5
// * don't include pager < 1 or pager > lastPage
// * Expected output using example:
// [9,10,11,12,13,14,15,16,17,18,19]
const page = 14 // by example
const lastPage = 40 // by example
const pagerPages = page => {
let newArray = []
for (let i = page - 5; i <= page + 5; i++) {
i >= 1 && i <= lastPage ? newArray.push(i) : null
}
return newArray
}
Run Code Online (Sandbox Code Playgroud)
我想避免使用Array.push,可能还有for循环,但我不确定在这种情况下如何实现它.
const pageRange = (lastPage, page) => ((start, end) => Array.from({length: end - start + 1}, (_,i) => i + start))(Math.max(1, page - 5), Math.min(lastPage, page + 5));
const newArray = pageRange(40, 14);
Run Code Online (Sandbox Code Playgroud)
这是一种纯粹的功能性方法.它用于Math.max/min实现边界,然后使用IIFE传递这些边界,Array.from这将创建一个end - start元素数组,并且每个元素都将是由startvalue增加的数组中的位置.
PS:IMO你的代码实际上更简洁(除了那个不必要的三元组)并且比mys更具可读性,只是说......
函数式编程不限于reduce, filter, 和map; 它是关于功能的。这意味着我们不必依赖不正当的知识,例如可以将Array.from ({ length: x })具有length属性的对象视为数组。这种行为对于初学者来说是令人困惑的,对其他人来说是精神负担。它认为您会喜欢编写更清晰地编码您的意图的程序。
reduce从 1 个或多个值开始,然后减少到(通常)一个值。在这种情况下,您实际上想要a (或)的反转,这里称为。不同之处在于我们从单个值开始,然后将其扩展或展开为(通常)多个值。reducefoldunfold
我们从一个简化的例子开始,alphabet. 我们从初始值 开始展开,即字母97的字符代码a。当字符代码超过122字母的字符代码时,我们停止展开z。
const unfold = (f, initState) =>
f ( (value, nextState) => [ value, ...unfold (f, nextState) ]
, () => []
, initState
)
const alphabet = () =>
unfold
( (next, done, char) =>
char > 122
? done ()
: next ( String.fromCharCode (char) // value to add to output
, char + 1 // next state
)
, 97 // initial state
)
console.log (alphabet ())
// [ a, b, c, ..., x, y, z ]Run Code Online (Sandbox Code Playgroud)
上面,我们为我们的状态使用单个整数,但其他展开可能需要更复杂的表示。下面,我们通过展开复合初始状态来展示经典的斐波那契数列,[ n, a, b ]其中n是递减计数器,a和b是用于计算序列项的数字。这演示了unfold可以用于任何种子状态,甚至是数组或对象。
const fib = (n = 0) =>
unfold
( (next, done, [ n, a, b ]) =>
n < 0
? done ()
: next ( a // value to add to output
, [ n - 1, b, a + b ] // next state
)
, [ n, 0, 1 ] // initial state
)
console.log (fib (20))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765 ]
Run Code Online (Sandbox Code Playgroud)
现在我们有信心写了pagination。同样,我们的初始状态是复合数据,[ page, count ]因为我们需要跟踪page要添加的内容以及count我们已经添加了多少页 ( )。
这种方法的另一个优点是您可以轻松地参数化诸如10or 之类的东西-5,+1并且有一个合理的语义结构可以放置它们。
const unfold = (f, initState) =>
f ( (value, nextState) => [ value, ...unfold (f, nextState) ]
, () => []
, initState
)
const pagination = (totalPages, currentPage = 1) =>
unfold
( (next, done, [ page, count ]) =>
page > totalPages
? done ()
: count > 10
? done ()
: next (page, [ page + 1, count + 1 ])
, [ Math.max (1, currentPage - 5), 0 ]
)
console.log (pagination (40, 1))
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
console.log (pagination (40, 14))
// [ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]
console.log (pagination (40, 38))
// [ 33, 34, 35, 36, 37, 38, 39, 40 ]
console.log (pagination (40, 40))
// [ 35, 36, 37, 38, 39, 40 ]Run Code Online (Sandbox Code Playgroud)
以上,有两个条件会导致调用done (). 我们可以使用折叠这些||,代码读起来更好一点
const pagination = (totalPages, currentPage = 1) =>
unfold
( (next, done, [ page, count ]) =>
page > totalPages || count > 10
? done ()
: next (page, [ page + 1, count + 1 ])
, [ Math.max (1, currentPage - 5), 0 ]
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
333 次 |
| 最近记录: |