最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Looking for function identical to lodash's [_.set]() - Stack Overflow

programmeradmin1浏览0评论

I'm looking for a function identical to lodash's _.set except it should return a new object without modifying the original. Are there any implementations of this?

Right now I'm deep-cloning and then setting:

let data = _.cloneDeep(this.state.data);
_.set(data, name, value);
this.setState({data})

But I don't think it's necessary to do a full deep clone, we'd just need to do a shallow clone of the object at the deepest level, no?

e.g.

let oldData = { 'a': [{ 'b': { 'c': 3 }, 'd': {'e': 4} }] };
let newDate = withValue(oldData, 'a[0].b.c', 5);

The proposed withValue function would perform a shallow clone of a, a[0] and a[0].b and then modify the new a[0].b.c to 5. We would not need to make a copy of a[0].d.

I'm looking for a function identical to lodash's _.set except it should return a new object without modifying the original. Are there any implementations of this?

Right now I'm deep-cloning and then setting:

let data = _.cloneDeep(this.state.data);
_.set(data, name, value);
this.setState({data})

But I don't think it's necessary to do a full deep clone, we'd just need to do a shallow clone of the object at the deepest level, no?

e.g.

let oldData = { 'a': [{ 'b': { 'c': 3 }, 'd': {'e': 4} }] };
let newDate = withValue(oldData, 'a[0].b.c', 5);

The proposed withValue function would perform a shallow clone of a, a[0] and a[0].b and then modify the new a[0].b.c to 5. We would not need to make a copy of a[0].d.

Share Improve this question edited May 1, 2016 at 22:26 mpen asked May 1, 2016 at 21:42 mpenmpen 283k281 gold badges890 silver badges1.3k bronze badges 12
  • No, that's not sufficient. This would not guarantee a mutation of the other object does not change the new one. So you either must deep-clone the plain JS object, or use something that wraps data structures for you (like immutablejs). – zerkms Commented May 1, 2016 at 21:46
  • As of react - "unsetting" will not help, since react merges the passed object with the existing one. – zerkms Commented May 1, 2016 at 21:48
  • @zerkms What if I know the old one (this.state.data) will never be mutated so I don't have to worry about it altering the new one? – mpen Commented May 1, 2016 at 21:48
  • {...data, [name]: value} <--- then that – zerkms Commented May 1, 2016 at 21:49
  • @zerkms React does a shallow merge when calling setState doesn't it? I've put all this data in this.state.data so unsetting something under this.state.data should unset it forreal, no? – mpen Commented May 1, 2016 at 21:50
 |  Show 7 more ments

2 Answers 2

Reset to default 6

lodash/fp as Emil suggested should work.

Example:

const setIn = require('lodash/fp/set');
this.setState({data: setIn(name, value, this.state.data)});

N.B. the argument order is different than regular lodash.

This is going to be a multi-part answer.

Immutable set:

As you're using lodash, you can use the FP version of lodash and use .set (or .setWith to be able to supply an object path) which will do an immutable update.

Or, as this looks like a React codebase you can use the $set helper of React.

Or you can just use the Spread Operator:

const newObj = {...oldObj, prop: newValue }

Or Object.assign:

const newObj = Object.assign({}, oldObj, { prop: newValue });

Performance:

As you're mentioning performance (and not just deeply cloning an object) you might want to look in to an immutable framework. The more developed codebases increase performance by different measures. E.g. here's what immutable.js says:

These data structures are highly efficient on modern JavaScript VMs by using structural sharing via hash maps tries and vector tries

...and Mori says:

Efficient immutable data structures - no cloning required [...] Modern JavaScript engines like V8, JavaScriptCore, and SpiderMonkey deliver the performance needed to implement persistent data structures well.

发布评论

评论列表(0)

  1. 暂无评论