Javascript 如何用Ramda模拟lodash.set
我正在学习拉姆达,我很困惑。我想制作一个集合函数,其工作原理与lodash.set函数类似。但是,当我在对象中存在的路径上尝试以下操作时,它似乎按预期工作,但是当我使用它创建新路径时,它添加了这个奇怪的数组Javascript 如何用Ramda模拟lodash.set,javascript,ramda.js,Javascript,Ramda.js,我正在学习拉姆达,我很困惑。我想制作一个集合函数,其工作原理与lodash.set函数类似。但是,当我在对象中存在的路径上尝试以下操作时,它似乎按预期工作,但是当我使用它创建新路径时,它添加了这个奇怪的数组 const R = require('ramda') const set = (object, path, value) => R.set(R.lensPath(path), value, object); const foo = { moo: { goo: 'goo'
const R = require('ramda')
const set = (object, path, value) => R.set(R.lensPath(path), value, object);
const foo = {
moo: {
goo: 'goo'
}
}
set(foo, ['moo', 'goo', 'boo'], 'roo'); // { moo: { goo: { '0': 'g', '1': 'o', '2': 'o', boo: 'roo' } } }
所以结果是://{moo:{goo:{0':'g',1':'o','2':'o',boo:'roo'}}
当我期望它是://{moo:{goo:{boo:'roo'}}
为什么要按索引添加这些字符?如何使用Ramda实现lodash.set函数
这似乎是不想要的行为。为什么会有人想让拉姆达强迫绳子 我认为这是一个不同的问题。当
foo.moo.goo
是一个字符串时,您正在编写的代码应该执行与foo.moo.goo.boo='roo'
模糊等效的操作。这当然会引发一个错误,例如无法在字符串“goo”上创建属性“boo”
洛达斯回答说:“哦,你一定是指foo.moo.goo={boo:roo'}
”这是一个完全合理的猜测。但这只是猜测。库是否应该抛出如上所述的错误?这可能是最合乎逻辑的做法
Ramda(免责声明:我是它的作者之一)做出了不同的选择。它假设你说的是真的。您想要更新foo.moo
的goo
属性,方法是将其boo
属性设置为'roo'
。然后它就这样做了。但是,当它像其他地方一样更新这样的属性时,它不会改变原始数据,而是为您构建一个新的输出,复制旧对象的属性,但新路径除外,它会相应地设置。好的,您的旧对象('goo'
)有三个属性,{0:g'}
,{1:o'}
,以及{2:o'}
,Ramda的assocPath
(执行此任务的lensPath
也使用公共函数)然后与{boo:roo'}
合并成一个对象
但我在这里夸大了。拉姆达从未真正做出过这样的选择。这仅仅是实施过程中出现的问题assocPath
只知道两种类型:数组和对象。它只知道如何重构这些类型。实际上,它可以作为数组和其他数组使用。由于您的foo.moo
不是数组,因此它将其视为对象
如果你想看到这种行为改变,a,甚至更好的a会得到公平的听证。我可以向你保证
但我预计会有很多阻力
拉姆达的哲学与洛达斯的哲学截然不同。洛达斯强调灵活性<例如,code>set允许您以数组或字符串的形式编写路径,其中有两个示例
\uu0.set(对象'a[0].b.c',4);
_.set(对象,['x','0','y','z'],5);
许多函数都有可选参数。它可以自由地修改提供给它的数据。它的设计宗旨是“为尽可能多的开发人员提供高质量的实用方法,重点关注一致性、兼容性、定制和性能。”
相比之下,拉姆达对灵活性的担忧要小得多。Ramda更重要的目标是简单性。它的API没有可选参数。当一个参数允许多种类型时,这只是因为它们共享一个更高的抽象。提供给assocPath
的路径是一个数组,并且仅是一个数组;它通过注意每个path元素是字符串还是整数来处理对象与数组。当然,拉姆达从不改变你的输入数据
拉姆达对牵手也不感兴趣。哲学通常是垃圾进,垃圾出。这个案子似乎已经进入了这一领域。拉姆达愿意把{moo:{goo:'goo'}}
转换成{moo:{goo:{boo:'roo'}}}
。但是你必须更明确地告诉它:assoc(['moo','goo'],{boo:'roo'})
因此,要求改变这一点可能是一个困难的销售。。。但这是一个友好的人群。如果你认为它很重要的话,请随时提出来
我觉得我只需要从lodash导入set
函数,以防止意外行为
不过,请记住,这些行为是多么的不同。最大的区别是lodash正在改变它的输入,而Ramda不会这样做。他们对哪些值需要增强,哪些值需要替换有不同的想法(如当前示例中所示)。当然,他们的签名是不同的。它们在数组索引方面有不同的行为。(例如,我想不出在lodash的集合中添加一个字符串键为“0”的对象的方法。当你调用assocPath(['grid','width',newVal,myObj)
之类的东西时,Ramda当然不会包含一个构造好的矩形,而lodash会很高兴地对内部矩形对象进行变异。)
换句话说,它们是不同的行为,为不同的目的而设计。如果lodash的行为是你想要的,那么一定要包括在内。但是,如果您在大多数实用程序工作中使用Ramda,请注意它们的原理有多么不同。您要求它在字符串上设置一个新属性,但实际上没有一个理想的解决方案是js。Ramda通过首先将字符串强制到具有索引属性的对象,然后添加新属性来尝试不丢失信息。Ramda已经有一个类似于函数-R.assocPath的集合,但是字符串也会有同样的强制问题。这似乎是不需要的行为。为什么会有人想让拉姆达强迫绳子?这种行为有什么好处?我觉得我必须从lodash中导入set函数以防止意外行为。