1.第一步
2.结合功能
3.部分使用(咖喱)
4.声明式编程
5.典型符号
6.不变性与对象
7.不变性和数组
8.镜片
9.结论
这篇文章是关于函数式编程的一系列文章的第八篇,名为Ramda Style Thinking。
在第六部分和第七部分中,我们学习了如何以声明性和不变的方式读取,更新和转换对象和数组元素的属性。
Ramda还提供了用于执行这些操作的更通用的工具,称为镜头。
什么样的镜片?
镜头将吸气功能和设定功能组合为一个机构。 Ramda提供了一组用于处理镜头的功能。
我们可以将镜头视为专注于大型数据结构的特定部分的事物。
如何制作镜头?
在Ramda中创建镜头的主要方法是使用镜头功能。 lens
具有吸气功能和设定功能,并返回新的镜头。
const person = { name: 'Randy', socialMedia: { github: 'randycoulman', twitter: '@randycoulman' } } const nameLens = lens(prop('name'), assoc('name')) const twitterLens = lens( path(['socialMedia', 'twitter']), assocPath(['socialMedia', 'twitter']) )
在这里,我们使用prop
和path
方法作为我们的assocPath
函数,并使用assoc
和assocPath
作为我们的assocPath
函数。
请注意,我们使用属性名称和这些函数所需属性的路径复制了参数。 幸运的是, Ramda为最常见的镜头使用情况提供了很酷的快捷方式: lensProp , lensPath和lensIndex 。
lensProp
创建一个聚焦于对象属性的镜头lensPath
创建一个镜头,聚焦于对象的附加属性lensIndex
创建一个聚焦在数组元素上的镜头
我们可以使用lensProp
和lensPath
重写上述镜头:
const nameLens = lensProp('name') const twitterLens = lensPath(['socialMedia', 'twitter'])
它简单得多,并且消除了重复项。 在实践中,我发现我几乎不需要原始的lens
功能。
我该怎么办?
好吧,太好了,我们制造了一对镜片。 现在我们该怎么办?
Ramda提供三种镜头功能。
view(nameLens, person) // => 'Randy' set(twitterLens, '@randy', person) // => { // name: 'Randy', // socialMedia: { // github: 'randycoulman', // twitter: '@randy' // } // } over(nameLens, toUpper, person) // => { // name: 'RANDY', // socialMedia: { // github: 'randycoulman', // twitter: '@randycoulman' // } // }
请注意, set
和over
返回整个对象,并带有镜头聚焦的更改值。
结论
如果我们有一个非常复杂的数据结构,希望在调用代码时从中抽象出来,那么镜头就可以派上用场了。 除了提供每种可用属性的结构或提供吸气剂,设置器和变压器之外,我们还可以提供透镜。
客户代码可以通过使用view
, set
和over
来进一步使用我们的数据结构,而无需链接到数据结构的确切形式。
下一个
现在我们知道Ramda提供的很多信息; 通常,足以完成我们在程序中执行的所有操作。 本系列的最后一篇文章概述了已研究的内容,并提到了我们可能希望自己探索的其他一些主题。