如何将对象的属性应用于函数?

How to apply properties of an object to functions?

我想对某些对象属性应用不同的函数。假设我有这个对象:

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']
}

使用函数式编程和 point free 实现此目的的最佳方法是什么,如果您可以包含使用 Ramda 的示例,我将不胜感激,谢谢!

使用 Ramda,您正在查看 evolve 函数:

Creates a new object by recursively evolving a shallow copy of object, according to the transformation functions. All non-primitive properties are copied by reference.

您可能需要即时定义 "transform" 函数;我打赌你不想将 'Lucas' 添加为每个人的朋友。希望这足以让您入门。

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>


无点风格不是唯一的方式

⚠️

请注意,我已经能够实现这种无点样式,因为我可以对每个转换函数进行硬编码。如果您需要即时制作一个转换对象,那么这样做的无点样式可能很快就变得不可读了。

像往常一样,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 (closer to the above implementation than prepend。)

关于评论中提出的 VLAZ 主题的更完整讨论可以在 中找到。