Link to CodePen https://codepen.io/jaspercreel/pen/Mvaodp
Basically, my function will look something like this:
const Factory = (args) => {
const state = {
args
}
const methods = {
getState() => {
return args;
},
setState(args) => {
state.args = args;
},
doStuffWithState() => {
let args = this.getState();
function(args) {
return args plus something else;
}();
}
}
return Object.assign({}, methods);
}
The problem is that whenever I call doStuffWithState() it changes the state object. I thought I would be safe creating a new variable with the returned state, but I learned that when referencing an object you are only creating a new reference. So my question is this, how can I create immutable state that can be referenced but not changed (except by helper functions) in a factory function?
My end goal is to create a sorter factory function that will create an object that takes arrays and sorts and searches them in different ways. I want to be able to store a default array in the sorter that can be referenced to return different sorting options but not changed. Any advice?
One approach would be to store the JavaScript object as a JSON
string with JSON.stringify()
and use JSON.parse()
to parse the JSON
string to a JavaScript object, which does not reference the original object passed that is stored as a string.
You can also utilize Promise
to return a JavaScript object reflecting properties of JSON
string, passed to Object.assign()
, which can return modified properties or values of original object, without affecting original object passed to Factory
, which returns a Promise
value as the JSON
string format of the original passed object.
// `const` declaration cannot be changed or deleted const Factory = (args) => Promise.resolve(JSON.stringify(args)); const state = Factory({ abc: [1, 2, 3] }); state.then(data => console.log(data)); // `{"abc":[1,2,3]}` // change object passed to `Factory` state.then(data => Object.assign(JSON.parse(data), { abc: JSON.parse(data).abc.concat(4, 5, 6) })) // do stuff with modified `JSON` `args` as JavaScript object.then(res => {console.log(res); return res}) // `{"abc":[1,2,3,4,5,6]}`.then(res => // `res`: `{"abc":[1,2,3,4,5,6]}` // `state` `Promise` value is original object // as valid `JSON` `{"abc":[1,2,3]}` // return original `args` as `JSON` string state.then(data => {console.log(res, data); return data}) ) // original `args` as JavaScript object.then(o => console.log(JSON.parse(o)))
I appreciate all the answers and comments guys. It turns out I was being very dumb. So in my tests I was sometimes able to return a value without altering the original and sometimes not, and I could not figure out why. Now I know it is because in my tests that altered the state, I was calling sort() on an array, and sort is an in-place function. It alters the original array.
Such a small oversight on my part, but I consider it a learning experience. Thanks again for the effort in the help guys. Hopefully my dumb mistake can be a learning experience for others too.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.