我想将不同的功能应用于某些对象属性。可以说我有这个对象:
const person = {
name: 'John',
age: 30,
friends: [],
};
并且我有一些要应用于这些属性的函数:
const upperCase = str => str.toUpperCase() //for the name
const add10 = int => int + 10 // for the age
const addFriend = (value,list) => [...list,value] // adding a friend
这应该是结果:
const person = {
name: 'JOHN',
age: 40,
friends: ['Lucas']
}
使用函数式编程和免积分实现这一目标的最佳方法是什么,如果您可以包括使用Ramda的示例,我将不胜感激,谢谢!
答案 0 :(得分:3)
使用Ramda,您正在查看evolve
函数:
根据转换函数,通过递归演化对象的浅表副本来创建新对象。所有非原始属性均通过引用复制。
您可能需要即时定义“转换”功能;我敢打赌,您不想将“卢卡斯”添加为每个人的朋友。希望这足以让您入门。
const transform =
evolve(
{ name: toUpper
, age: add(10)
, friends: prepend('Lucas')
});
console.log(
transform(person)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {evolve, toUpper, add, prepend} = R;</script>
<script>
const person =
{ name: 'John'
, age: 30
, friends: []
};
</script>
无点样式不是唯一的方法
⚠️
请注意,我已经能够实现这种无点样式,因为我可以对每个转换函数进行硬编码。如果您需要即时制作转换对象,则这种无点样式可能很快就会变得难以理解。
答案 1 :(得分:2)
与往常一样,customcommander提供了一个很好的答案。 Ramda的evolve
正是为此目的而设计的,在简单的情况下,它可以提供完全无分的答案。
Ramda的作者之一,我非常喜欢它的功能。但是应该注意,构建自己的许多版本(包括此版本)非常容易,尤其是在您只关心在对象根目录更新密钥的简单情况下。 (Ramda重复出现在嵌套的spec对象中,至少涉及更多的对象。)
因此,如果您没有Ramda方便的话,则可以像这样轻松编写此函数的自定义版本:
const evolve = (spec, keys = Object .keys (spec)) => (obj) =>
Object .entries (obj) .reduce (
(a, [k, v]) => ({...a, [k]: keys .includes (k) ? spec [k] (v) : v})
, {}
)
const upperCase = str => str.toUpperCase() //for the name
const add10 = int => int + 10 // for the age
const addFriend = (value) => (list) => [...list,value] // adding a friend
const person = {name: 'John', eys: 'blue', age: 30, friends: [], hair: 'red'}
console .log (
evolve ({name: upperCase, age: add10, friends: addFriend('Lucas')}) (person)
)
这与性能最高的代码相去甚远。 Rich Snapp的一篇精彩文章解释了为什么以及如何修复它。但是我个人会坚持这样做,除非这成为我应用程序中的瓶颈。
当然,如customcommander所指出的那样,您的每个帮助也都有Ramda函数:toUpper
,add
,append
(比{{3} }。
可以在prepend
中找到有关注释中提出的VLAZ主题的更完整讨论。