We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.
FYI, the object spread proposal is in stage 3, according to https://github.com/tc39/pro..., and many environments support it without a polyfill, including Node >= 8.6.0, and current versions of Chrome and Firefox
If you want to manipulate complex nested plain JSON / JavaScript data structures in an immutable manner, you might want to check out my https://github.com/calmm-js... library. It is a comprehensive optics library for JavaScript that makes it very easy to manipulate complex nested data structures in various ways.
that was usefull
thanks
Can we use a simple solution as mentioned in the below link to deep clone objects ?
https://stackoverflow.com/a...
You can although it seems kinda counterintuitive to use serialization for cloning objects. I would say it makes more sense to use something like lodash _.cloneDeep(). I did some naive benchmarks and it did not seem to really differ in performance, the benefit of cloneDeep is that it keeps the prototype, that would be benficial when you have an object constructed from a class or constructor function with methods.
Hi,
Can anyone help me with a simple project set up where I can run these samples from my CLI? At the moment I hit the problem of spread operator for object literals and I have tried so many different sources out there on how to set up babel-cli and presets and plugins but I fail to run my .js file from the command line if I use spread operator on an object. Any help would be appreciated. Any github link...Thanks
For the object spread to work you only need to update to the latest nodjes version. https://nodejs.org/en/
Babel is for when you want this to work with all browser versions, it will then replace those spread operators with something like Object assign.
Thanks Niels,
It only works on the array at the moment, it does not work on Object. I used the Object.assign for that part but I so much wish I did not have to. My node version is up-t-date.
So what does node -v say?
v7.10.0
That means you do not have the latest one. You need at least v8. Check here for the latest versions: https://nodejs.org/en/
you are amazing! Thanks for bearing with me, it solved the problem. I updated to v8.9.4 and now the spread works for objects too. Thank you so much :)
Nice article!
Something I've found very useful and readable in order to do the deletion of a key in an object has been the use of the spread operator like this (if we want to remove the key called 'el2'):
let {el2, ...rest} = {el1: 'el1', el2: 'el2', el3: 'el3'};
console.log(rest) //=> {el1: 'el1', el3: 'el3'}
Thanks!
Hey! Nice article. That is the way I was doing things (and the one I like most) until I saw some less experienced people doing strange things when trying to create new complex objects when they needed to update just a prop but a very nested one.
I think libraries as Immutable are really good for that cases, also really prevent immutability as with vanilla javascript someone can also make mistakes. That together with a very nice performance boost thanks to persistent data structures made me really decide to use Immutable-js
You can use delete:
function immutableDelete(prop, ob){
const immutableObjectWithDeletedProp = Object.assign({}, ob);
delete immutableObjectWithDeletedProp[prop];
return immutableObjectWithDeletedProp;
}
const person = { name: 'John', test: 'delete me', age: 28 };
const newPerson = immutableDelete('test', person);
console.log(person === newPerson); // -> false
console.log(newPerson.test) // -> undefined
console.log(person.test); // -> delete me
That is also a nice solution :)
Love it
This is a nice way you've described to code and then rely on shallow comparisons. Have you also considered [seamless-immutable](https://github.com/rtfeldma... In a way it is like a typechecker in development that enforces immutability without forcing one to use as much extra syntax as Immutable.js.
Looks nice and pretty small!
Hey there, very nice article.
One part, however, looks misleading to me - the array prototype methods, map, filter, etc. From the code examples and description given it might look as if they're some magic methods that clone arrays without mutations, but they're not, of course. And some less experienced developers can fall into this trap.
For example:
var list1 = [{ a: 1, b: 2}, { a: 11, b: 22}];
var list2 = list1.map((item) => { item.b = 33; return item; });
Now the real fun begins:
list1 === list2 // false, but
list1[0].b // 33, of course, since it was passed by reference to map callback
More fun:
list2[0].b = 55;
list1[0].b // 55 also, those are reference to same object
To sum it up, we have two arrays, which are not equal by ===, but contain exactly the same objects in exacly the same order.
Not cool :)
Of course, that can be solved with spread or assign({}, ...), but you have to know what you're doing at all steps.
Consider this:
var test1 = { a: { b: 1 } };
var test2 = Object.assign({}, test1);
test2.a.b = 2;
console.log(test1.a.b) // 2
It clones the props one level deep, any object props are still refs.
Maybe it's better and easier to use immutablejs, still not sure about this.
Hey Alex, thanks for you comment!
Array methods not deep cloning is actually a good thing, because if an object contents did not actually change, it's nice to keep the same reference!
Performance wise you don't want to deep clone everything, it's not necessary. The only thing that is changing is the array itself, not the objects inside.
When doing it this way you can easily check if the object did actually change by doing ===. Now view libraries like React for instance can render with better performance because they can check if objects are the same, even if they come out of a filtered array.
If you DO change the actual contents of the object inside (with a map for instance) then you should make sure you do this in an Immutable way of course. Because in that case the object did change.
Immutable.JS by the way will behave the same as a native method:
const obj1 = { number: 1 }
const obj2 = { number: 2 }
const list = Immutable.List([obj1, obj2])
const list2 = list.filter(o => o.number === 1)
console.log(list.get(0) === list2.get(0))
Again this is desired behaviour :). Just make sure you never mutate the objects directly.
Ok, I just thought it's a good idea to elaborate a bit more on these, since they're not obvious. :)
For sorting, you could use a spread,
[...characters].sort(), instead ofcharacters.slice().sort(). A spread can also be used to achieve an immutable push,[...characters, newCharacter].