visit
Here's a problem. You have an object in your code exposed via an
export
. You also have a function in the same file (also exported) consuming that object directly.const info = {
name: 'sam'
age: 23,
city: 'New York City'
}
function printInfo() {
console.log(info)
}
export {
info,
printInfo
}
How can we prevent such mutations and manipulations from persisting and guarantee that our function,
printInfo
, can run with peace of mind? The easy way out would be to wrap the object in a function and have all other references invoke the function to get a new, crisp, clean, copy. To prevent this solution, let's make the problem more contrived! We want mutations to persist across the lifecycle of our application with one exception! Our function should always consume the object in its original untouched state.
Our goals:const wrappedPrintInfo = (obj) => () => console.log(obj);
export const printInfoTwo = wrappedPrintInfo(obj)
Create a function called
wrappedPrintInfo
that accepts an object as its parameter and returns a function which when invoked logs that object. Then keep this wrapped version private to the file using it to generate our printInfo function which we then expose as normal.As always, nothing works on the first try. The object is still passed by reference even through the currying and changes to
obj
in one part of your application will persist through printInfoTwo
. Unfortunately there's no getting around the pass by reference issue with just a curried function. The curried function must make its own internal copy.const wrapedPrintInfo = (obj) => {
const copied = Object.assign({}, obj);
return () => {
console.log(copied);
}
}
const printInfoThree = wrappedPrintInfo(obj)
Now we still use a curried function but inside the first layer we use
Object.assign
to create a copy of the passed in object and use this copy in the returned function. Effectively we use a closure to create a private copy of the passed in object and then return the real function in the closure.Currying the function and using a closure to make a copy of the object allows for the function to only runs once when first creating the
printInfo
function. We also don't have to rewrite a potentially massive object in our function's scope leaving our code DRY.Finally, since this is a curried function, should we ever need to reuse it for another object, we can do so easily with the same benefits by exposing the wrapper and currying with any other object. The biggest benefit is a clear separation of concerns where two parts of our app remain completely untangled.