{"data":{"site":{"siteMetadata":{"title":"Dev Mastery","author":"Bill Sourour"}},"markdownRemark":{"id":"b0df1814-df44-5524-ad8a-7954127b6cdf","excerpt":"I wrote my first few lines of JavaScript not long after the language was…","html":"

I wrote my first few lines of JavaScript not long after the language was invented. If you told me at the time that I would one day be writing a series of articles about elegant patterns in JavaScript, I would have laughed you out of the room. I thought of JavaScript as a strange little language that barely even qualified as “real programming.”

\n

Well, a lot has changed in the 20 years since then. I now see in JavaScript what Douglas Crockford saw when he wrote JavaScript: The Good Parts: “An outstanding, dynamic programming language … with enormous, expressive power.”

\n

So, without further ado, here is a wonderful little pattern I’ve been using in my code lately. I hope you come to enjoy it as much as I have.

\n

Please note : I’m pretty sure I did not invent any of this. Chances are I came across it in other people’s code and eventually adopted it myself.

\n

Receive an object, return an object (RORO)

\n

Most of my functions now accept a single parameter of type object and many of them return or resolve to a value of type object as well.

\n

Thanks in part to the destructuring feature introduced in ES2015, I’ve found this to be a powerful pattern. I’ve even given it the silly name, “RORO” because… branding? 🤷‍♂️

\n

Note: Destructuring is one of my favorite features of modern JavaScript. We’re going to be taking advantage of it quite a bit throughout this article, so if you’re not familiar with it, here’s a quick video to get you up to speed.

\n

youtube: https://youtu.be/-vR3a11Wzt0\nThe inimitable Beau Carnes explains ES2015 Destructuring syntax in about 6 minutes.

\n

Here are some reasons why you’ll love this pattern:

\n\n

Let’s look at each one.

\n

Named Parameters

\n

Suppose we have a function that returns a list of Users in a given Role and suppose we need to provide an option for including each User’s Contact Info and another option for including Inactive Users, traditionally we might write:

\n
function findUsersByRole (\n  role,\n  withContactInfo,\n  includeInactive\n) {...}
\n

A call to this function might then look like:

\n
findUsersByRole(\n  'admin',\n  true,\n  true\n)
\n

Notice how ambiguous those last two parameters are. What does “true, true” refer to?

\n

What happens if our app almost never needs Contact Info but almost always needs Inactive Users? We have to contend with that middle parameter all the time, even though it’s not really relevant (more on that later).

\n

In short, this traditional approach leaves us with potentially ambiguous, noisy code that’s harder to understand and trickier to write.

\n

Let’s see what happens when we receive a single object instead:

\n
function findUsersByRole ({\n  role,\n  withContactInfo,\n  includeInactive\n}) {...}
\n

Notice our function looks almost identical except that we’ve put braces around our parameters. This indicates that instead of receiving three distinct parameters, our function now expects a single object with properties named role, withContactInfo, and includeInactive.

\n

This works because of a JavaScript feature introduced in ES2015 called Destructuring.

\n

Now we can call our function like this:

\n
findUsersByRole({\n  role: 'admin',\n  withContactInfo: true,\n  includeInactive: true\n})
\n

This is far less ambiguous and a lot easier to read and understand. Plus, omitting or re-ordering our parameters is no longer an issue since they are now the named properties of an object.

\n

For example, this works:

\n
findUsersByRole({\n  withContactInfo: true,\n  role: 'admin',\n  includeInactive: true\n})
\n

And so does this:

\n
findUsersByRole({\n  role: 'admin',\n  includeInactive: true\n})
\n

This also makes it possible to add new parameters without breaking old code.

\n

One important note here is that if we want all the parameters to be optional, in other words, if the following is a valid call…

\n
findUsersByRole()
\n

… we need to set a default value for our parameter object, like so:

\n
function findUsersByRole ({\n  role,\n  withContactInfo,\n  includeInactive\n} = {}) {...}
\n

An added benefit of using destructuring for our parameter object is that it promotes immutability. When we destructure the object on its way into our function we assign the object’s properties to new variables. Changing the value of those variables will not alter the original object.

\n

Consider the following:

\n
const options = {\n  role: 'Admin',\n  includeInactive: true\n}\n\nfindUsersByRole(options)\n\nfunction findUsersByRole ({\n  role,\n  withContactInfo,\n  includeInactive\n} = {}) {\n  role = role.toLowerCase()\n  console.log(role) // 'admin'\n  ...\n}\n\nconsole.log(options.role) // 'Admin'
\n

Even though we change the value of role the value of options.role remains unchanged.

\n

It’s worth noting that destructuring makes a_ shallow _copy so if any of the properties of our parameter object are of a complex type (e.g. array or object) changing them would indeed affect the original.

\n

Cleaner Default Parameters

\n

With ES2015 JavaScript functions gained the ability to define default parameters. In fact, we recently used a default parameter when we added ={} to the parameter object on our findUsersByRole function above.

\n

With traditional default parameters, our findUsersByRole function might look like this.

\n
function findUsersByRole (\n  role,\n  withContactInfo = true,\n  includeInactive\n) {...}
\n

If we want to set includeInactive to true we have to explicitly pass undefined as the value for withContactInfo to preserve the default, like this:

\n
findUsersByRole(\n  'Admin',\n  undefined,\n  true\n)
\n

How hideous is that?

\n

Compare it to using a parameter object like so:

\n
function findUsersByRole ({\n  role,\n  withContactInfo = true,\n  includeInactive\n} = {}) {...}
\n

Now we can write…

\n
findUsersByRole({\n  role: ‘Admin’,\n  includeInactive: true\n})
\n

… and our default value for withContactInfo is preserved.

\n

BONUS: Required Parameters

\n

How often have you written something like this?

\n
function findUsersByRole ({\n  role,\n  withContactInfo,\n  includeInactive\n} = {}) {\n  if (role == null) {\n    throw Error(...)\n  }\n  ...\n}
\n

Note: We use double equals (==) above to test for both null and undefined with a single statement.

\n

What if I told you that you could use default parameters to validate required parameters instead?

\n

First, we need to define a requiredParam() function that throws an Error.

\n

Like this:

\n
function requiredParam (param) {\n  const requiredParamError = new Error(\n   `Required parameter, \"${param}\" is missing.`\n  )\n\n  // preserve original stack trace\n  if (typeof Error.captureStackTrace ===function) {\n    Error.captureStackTrace(\n      requiredParamError,\n      requiredParam\n    )\n  }\n\n  throw requiredParamError\n}
\n

I know, I know. requiredParam doesn’t RORO. That’s why I said many of my functions — not all .

\n

Now, we can set an invocation of requiredParam as the default value for role, like so:

\n
function findUsersByRole ({\n  role = requiredParam('role'),\n  withContactInfo,\n  includeInactive\n} = {}) {...}
\n

With the above code, if anyone calls findUsersByRole without supplying a role they will get an Error that says Required parameter, “role” is missing.

\n

Technically, we can use this technique with regular default parameters as well; we don’t necessarily need an object. But this trick was too useful not to mention.

\n

Richer Return Values

\n

JavaScript functions can only return a single value. If that value is an object it can contain a lot more information.

\n

Consider a function that saves a User to a database. When that function returns an object it can provide a lot of information to the caller.

\n

For example, a common pattern is to “upsert” or “merge” data in a save function. Which means, we insert rows into a database table (if they do not already exist) or update them (if they do exist).

\n

In such cases, it would be handy to know wether the operation performed by our Save function was an INSERT or an UPDATE. It would also be good to get an accurate representation of exactly what was stored in the database, and it would be good to know the status of the operation; did it succeed, is it pending as part of a larger transaction, did it timeout?

\n

When returning an object, it’s easy to communicate all of this info at once.

\n

Something like:

\n
async saveUser({\n  upsert = true,\n  transaction,\n  ...userInfo\n}) {\n  // save to the DB\n  return {\n    operation, // e.g 'INSERT'\n    status, // e.g. 'Success'\n    saved: userInfo\n  }\n}
\n

Technically, the above returns a Promise that resolves to an object but you get the idea.

\n

Easy Function Composition

\n
\n

“Function composition is the process of combining two or more functions to produce a new function. Composing functions together is like snapping together a series of pipes for our data to flow through.” —  Eric Elliott

\n
\n

We can compose functions together using a pipe function that looks something like this:

\n
function pipe(...fns) {\n  return param => fns.reduce(\n    (result, fn) => fn(result),\n    param\n  )\n}
\n

The above function takes a list of functions and returns a function that can apply the list from left to right, starting with a given parameter and then passing the result of each function in the list to the next function in the list.

\n

Don’t worry if you’re confused, there’s an example below that should clear things up.

\n

One limitation of this approach is that each function in the list must only receive a single parameter. Luckily, when we RORO that’s not a problem!

\n

Here’s an example where we have a saveUser function that pipes a userInfo object through 3 separate functions that validate, normalize, and persist the user information in sequence.

\n
function saveUser(userInfo) {\n  return pipe(\n    validate,\n    normalize,\n    persist\n  )(userInfo)\n}
\n

We can use a rest parameter in our validate, normalize, and persist functions to destructure only the values that each function needs and still pass everything back to the caller.

\n

Here’s a bit of code to give you the gist of it:

\n
function validate(\n  id,\n  firstName,\n  lastName,\n  email = requiredParam(),\n  username = requiredParam(),\n  pass = requiredParam(),\n  address,\n  ...rest\n) {\n  // do some validation\n  return {\n    id,\n    firstName,\n    lastName,\n    email,\n    username,\n    pass,\n    address,\n    ...rest\n  }\n}\n\nfunction normalize(\n  email,\n  username,\n  ...rest\n) {\n  // do some normalizing\n  return {\n    email,\n    username,\n    ...rest\n  }\n}\n\nasync function persist({\n  upsert = true,\n  ...info\n}) {\n  // save userInfo to the DB\n  return {\n    operation,\n    status,\n    saved: info\n  }\n}
\n

To RO or not to RO, that is the question

\n

I said at the outset, most of my functions receive an object and many of them return an object too.

\n

Like any pattern, RORO should be seen as just another tool in our tool box. We use it in places where it adds value by making a list of parameters more clear and flexible and by making a return value more expressive.

\n

If you’re writing a function that will only ever need to receive a single parameter, then receiving an object is overkill. Likewise, if you’re writing a function that can communicate a clear and intuitive response to the caller by returning a simple value, there is no need to return an object.

\n

An example where I almost never RORO is assertion functions. Suppose we have a function isPositiveInteger that checks wether or not a given parameter is a positive integer, such a function likely wouldn’t benefit from RORO at all.

","wordCount":{"words":1424},"frontmatter":{"title":"Elegant patterns in modern JavaScript: RORO","date":"February 22, 2018","author":"Bill Sourour","spoiler":"Thanks to object destructuring in moder JavaScript there is now a much more flexible and clear way to write your functions. I call it RORO.","topic":"JavaScript","category":"Feature piece","imageCaption":"","imageDescription":"A capucino with a fancy swirly design in the foam that looks like a flower","image":{"childImageSharp":{"fluid":{"aspectRatio":1.6470588235294117,"src":"/static/e742adb7699341f57bfa21601e7099dc/9aef4/roro.jpg","srcSet":"/static/e742adb7699341f57bfa21601e7099dc/3683b/roro.jpg 140w,\n/static/e742adb7699341f57bfa21601e7099dc/7601b/roro.jpg 280w,\n/static/e742adb7699341f57bfa21601e7099dc/9aef4/roro.jpg 560w,\n/static/e742adb7699341f57bfa21601e7099dc/b1ee7/roro.jpg 840w,\n/static/e742adb7699341f57bfa21601e7099dc/6968c/roro.jpg 1000w","srcWebp":"/static/e742adb7699341f57bfa21601e7099dc/e3646/roro.webp","srcSetWebp":"/static/e742adb7699341f57bfa21601e7099dc/1d88e/roro.webp 140w,\n/static/e742adb7699341f57bfa21601e7099dc/c8d9f/roro.webp 280w,\n/static/e742adb7699341f57bfa21601e7099dc/e3646/roro.webp 560w,\n/static/e742adb7699341f57bfa21601e7099dc/1fea3/roro.webp 840w,\n/static/e742adb7699341f57bfa21601e7099dc/7c0d2/roro.webp 1000w","sizes":"(max-width: 560px) 100vw, 560px"}}}}}},"pageContext":{"dmPostId":"d59e7189b58cea520f4b7049f4318ab1","slug":"/blog/elegant-patterns-in-modern-javascript-roro/","previous":{"fields":{"slug":"/blog/don-t-do-it-at-runtime-do-it-at-design-time/","dmPostId":"8a1b523ae4f4f41a7fe75358c1c819c0"},"frontmatter":{"title":"Don’t do it at runtime. Do it at design time.","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUCAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAADAQL/2gAMAwEAAhADEAAAAVsWNA5XmkS//8QAGhAAAgMBAQAAAAAAAAAAAAAAAREAAhIDMf/aAAgBAQABBQK3Mg28c3opBif/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAXEQADAQAAAAAAAAAAAAAAAAABAhBR/9oACAECAQE/AQ2z/8QAHRAAAQIHAAAAAAAAAAAAAAAAABEhAQIQEjGRsf/aAAgBAQAGPwKCLoaWlvBjB//EABoQAQEAAwEBAAAAAAAAAAAAAAERACExEEH/2gAIAQEAAT8h3pUuB0muvhVBIWqZtKx+mf/aAAwDAQACAAMAAAAQyC//xAAWEQEBAQAAAAAAAAAAAAAAAAABEFH/2gAIAQMBAT8QHZ//xAAWEQEBAQAAAAAAAAAAAAAAAAAAIRH/2gAIAQIBAT8Q2hH/xAAdEAEAAwABBQAAAAAAAAAAAAABABEhMUFhgZHh/9oACAEBAAE/EF3jwap6sZbS3Ny73iumENIqbhKRJZUCwB1PPyFaBrjZ/9k=","tracedSVG":"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='400' height='267' viewBox='0 0 400 267' version='1'%3e%3cpath d='M0 39v38l2-1 6-2 4-2 7 3 13 5c7 1 12 3 16 5l6 1 6 1 5 1c8 2 12 8 12 19l2 5v6c-1 4-4 8-5 6h-1l-1-1c0-2-3-3-6-3-1 1-3 0-5-2-4-2-9-2-14 1-3 1-3 1-8-1l-6-4-7-7-4-2-8-4c-6-3-10-2-11 2l-2 4v21l1 2-1 1-1 4 1 4 1-2c0-2 4-6 4-4h6c7-2 20-1 24 1 2 0 2 0 2-2-1-2 0-3 4-2l2-1 8-1c10-1 12 1 14 19l2 12c0-2 1-2 6-3 7 0 13-2 10-3-2 0-3-1-1-3h7l2 1 2 1 4 1a711 711 0 0 1 38-1c8 0 13-1 20-4l12-5c4-2 7-3 7-5l2-2 1-2 1-1 1 4 1 4 1 1h-1c-1 0-2 1-2 5v5c-1 1-3-2-3-4v-4c-3-3-6 0-8 7-6 24-11 31-26 40-5 2-10 5-11 7l-10 5-6 3-3-3c-3-3-13-3-11 1l2 2c2 1 2 1 1 2v5l1 12c0 8 0 8 5 12 5 3 6 3 6 0l2-3c3-1 5-3 3-4l-3-1c-2 0-5-5-6-9 0-4 1-6 3-2 0 2 1 2 3 2 1-1 2 0 2 1-1 1 1 2 3 1v-3l3 2c2 2 2 2 2 0s5-5 7-4h1l8-1c8-1 12-2 6-2-3 0-8-2-5-2l3-2c1-2 5-3 9 0 5 2 6 2 6 0h-1c-1 0-2 0-2-2l1-1v-1c-2-3 0-3 3 0l4 6c1 5 3 6 7 5s9 1 7 3l3 1 4 1 6 1c4 0 5 0 4 2h-1c-1-2-2-1-4 0-1 2-1 2 1 6l2 6c-1 2 5 8 10 10l5 4v3l-2 1c-1 1-1 1 1 1l2-1 3 1c3 2 4 3 7 2l-1-1c-1-1-1-1 1-1 1 0 2-1 1-5l8-1 8-1 3-1 9-3 10-2c2 1 3 1 2 2-4 1-4 1-3 2h3l3-2v1c-2 0-2 1-1 1v1l-1 3v1l-1-1h-2c-2 3-2 4 0 2h2l2 1c4 0 6 1 5 2l1 1c1-1 4 3 3 5-1 3 31 7 32 4h2c0 1 3-1 3-4 0-1-9-5-14-6l-7-1-4 1c-1 1-3 0-6-1s-4-2-3-3l3 1h12l5 1 5 1h3l3 1 2 2 1 1h1l1 1 3 4 3 3h80v-13c0-9 0-12-1-11l-1 4h-2l-9-1c-4 0-15-15-12-17v-1l-1-1c0-2 4-3 8-3h8l2 1c1-1 3 1 2 4 0 2 0 2 3 2 2 0 3-1 3-6v-6h-4c-4 0-5-1-4-5 0-2 1-2 5-2 3 0 3 0 2-2l1-2 1-104V0H0v39M154 9c-5 3-7 5-4 5 5 0 6 1 4 3l-2 2h4l-2 1c-2 1-3 3 0 3l4 1c3 0 3-3 0-6-2-3-1-3 5-3 5 0 6-1 5-3 0-2-1-2-4-2-2 1-3 1-3-1-1-2-2-2-7 0m36 36c-15 5-25 21-20 28 2 2 10 2 11 0h4l5-1h8l6-1h11c1-2 2-2 4-1h8c3 0 5-1 7-3 5-4-3-15-15-21-8-4-20-4-29-1m61 8c-4 3-4 10-1 11h3l3-1c3 0 3 0 3-4 0-3-1-4-2-4l-2-2-2-2-2 2m-17 35c-1 1 0 3 3 3 2-1 3-1 4 1l2 2 4 2c3 3 17 4 17 1l-4-3-4-2h-3c-2 0-2 0-2-2s-1-2-4-2a440 440 0 0 1-13 0m-10 47c0 5 0 6 2 6v1c-1 1 0 2 1 3 2 3 3 7 1 7v1l1 2-2 1h-1l3 1c2 0 3 1 3 2 2 3 6-3 6-8v-4l1 4c1 4 0 13-2 17v6l1-1 2 1c2 1 2 1 3-1 0-2 2-3 2-1l7 2c10 1 12 2 12 4l2 3v3l-1 8v1h-1c-1-1-1-1-1 1 0 3 1 3 3 1 3-1 9-1 9 1l-2 2v1l1 2-2 1c-1-1-3 0-7 3l-4 3-7-2-9-4-8-2-7-2c-3-2-13-1-13 1l1 2h1c2-1 5 1 5 4l3 4 2 3 1 1c2-1 2 0 2 1 0 2 0 2 3 0l3-3 1 2 2 1 1-2 2-2h2v1l1 3c2 1 2 2 2 4s2 1 3-1c0-3 2-2 1 1 0 3 1 6 3 4s3-1 3 2l1 3 1-1h2l3 2v-6c-2-3 0-2 3 1 2 3 3 3 5 3 3-1 7-4 6-5l1-2v-2l1-1v-5h-4c-2 1-2 1-2-1v-10c0-2 0-3 3-3 3-1 5 1 5 4 0 2 1 3 2 3 2 1 2 1 2 3-1 2 0 2 8 2l12-1h4c0 2 2 1 3-2l3-4c3 0 2-2 0-2-4 0-6-3-4-5l2-3 3-1c3 0 3 0 3-3l-4-5c-4-7-2-8 8-5 4 1 5 1 3-2-1-2-7-7-9-7s-18-8-27-14l-6-3-3-1c-1-2-12-7-16-8l-4-2-2-1-5-1-6-4a109 109 0 0 0-21-6l-3-1c-3 0-3 0-3 7M1 163v7l5-1 9-3 10-3c6-1 7-2 4-3-2-2-12-3-16-2H7c-5-3-6-3-6 5m267-3c0 2 4 8 5 8s2 3 1 4l-1 3c-1 1-1 0-1-2 0-3 0-3-5-3s-6 1-3 3c2 1 6 7 7 10 1 2 3-1 3-3h-3l2-2 1-1 3-1 3-1h3l4 1c3 0 3 0 2-2l-3-3c-2 0-11-7-14-9l-4-2m100 1l1 2c2 1 2 4 0 6l-1 4-1 2-1 3-1 4c-2 1-1 2 1 2s2 0 1 1 0 1 3 1c4-1 9-4 11-8 1-2 1-3-1-6l-3-4-1-2-2-4c-3-2-6-3-6-1m-246 14l-2 1c-1-1-11 1-11 3h-3c0-1-1-1-1 1-1 2-1 2-4 0-4-2-12-4-12-2 0 1 2 2 6 2l6 2c3 2 3 2 1 2h-8l-1-1c-1 1 1 9 3 9l1 1c-1 2 6 1 8-1h4l1 1h2l4-3c4-1 7-7 8-13 0-5 0-5-2-2m222 3l-4 3c-4 2-7 7-6 8l2-1 2-1 1-2 2-1 2 1v3l1 3c2 0 3-4 1-6-1-1-2-2 0-2h1l3-1c3 0 5-2 3-4h-8m16 13c-2 1-2 3-3 7 0 8-1 7 2 8 2 0 3 1 3 5 0 6 3 9 9 9h5l1-3c2-1 2-6 0-8v-1c2 0 2-1 2-2-1-1 0-2 3-4 4-3 4-5 0-4l-3 1-1 1-2 1h-1l-2 1c0 3-2 3-5 2-1-1-2-2-1-3l2-4c0-4-5-7-9-6m-34 21c-5 1-12 6-11 8l-1 1c-4 0-9 4-8 7 0 4 2 4 4 3v-1c-2 0 0-1 2-2l10-4 2-1c1 1 1 1 0 0-2-1-1-2 2-1 2 0 2 1 1 2v2c2 0 2 0 0 1v2c1 1 2 2 1 3l1 2c1-1 2 0 2 1 1 2 3 1 2-1 0-2 0-2 1-1s4 1 4-1l-1-2v-3l1-3c0-4 4-6 5-3 1 2 1 2-1 2h-2l2 1c1 1 2 1 1 3h1v2l-2 1h-1l1 1 1 1v1c0-1 2 0 3 2 4 3 5 4 5 2l2 1 3 2c1 0 5-7 4-8v-1l-1-1-1-3-3-2c-1 1-1 0-1-2 1-4-2-9-5-9l-3-2c-2-1-6 0-6 3h-1l-8-4-5 1M32 228l3 4 3 4 4 7a1232 1232 0 0 1 16 23l27 1 27-1-2-1-5-2c-3-3-2-3 3-3 2 0 2 0 1-1l-3-2c-1 0-2 0-1-1l-2-2v-2l-2-1-7-2c-5 0-9-1-13-3l-9-3c-2 0-3-1-6-4l-4-4-4-1-12-2c-7 0-9-1-11-3l-3-1m253 2c-2 7-2 8 5 9l6 3c2 2 6 1 6-1 2-4 0-9-3-9l-3-2-6-2c-4-1-4-1-5 2M6 233l-1 2c-2 1 2 4 4 4l2 1c-1 1 0 2 1 4v2H2l2 2h2l4 3 6 4c4 1 4 3 1 4-3 2-3 3 0 3l4 3c2 3 11 3 11 0-1-3-4-7-6-7l-2-1-1-3c0-2 0-2 2-2v-1l-1-2c1-1 0-1-2-1l-1 2v2c-1 1-2-3-2-8l-2-2h-1c0-3-6-7-7-6s-1 1-1-1l-1-3-1 1m184 7l3 8 1 4 2 2 3 1c0 1 1 1 1-1 1-3 4-3 4 0-1 1 0 2 1 2l1-1 1-1c1 1 2 0 2-2-1-3-8-8-9-6h-1v-2l-1-1c0-2-3-4-4-3l-2-2c-3-6-4-5-2 2m-29 13l-7 3-10 2c-8 0-13 1-18 6l-3 3h35a251 251 0 0 0 35-2l-1-2c0-4-5-7-18-10h-13' fill='lightgray' fill-rule='evenodd'/%3e%3c/svg%3e","aspectRatio":1.6666666666666667,"src":"/static/16148bca642b5b4ffc145e9425c6220d/81b2d/wisdom-temp.jpg","srcSet":"/static/16148bca642b5b4ffc145e9425c6220d/de3a0/wisdom-temp.jpg 200w,\n/static/16148bca642b5b4ffc145e9425c6220d/fcaec/wisdom-temp.jpg 400w,\n/static/16148bca642b5b4ffc145e9425c6220d/81b2d/wisdom-temp.jpg 800w,\n/static/16148bca642b5b4ffc145e9425c6220d/09873/wisdom-temp.jpg 1200w,\n/static/16148bca642b5b4ffc145e9425c6220d/d0e89/wisdom-temp.jpg 1600w,\n/static/16148bca642b5b4ffc145e9425c6220d/a336b/wisdom-temp.jpg 2400w,\n/static/16148bca642b5b4ffc145e9425c6220d/7949e/wisdom-temp.jpg 5184w","srcWebp":"/static/16148bca642b5b4ffc145e9425c6220d/9fbef/wisdom-temp.webp","srcSetWebp":"/static/16148bca642b5b4ffc145e9425c6220d/f9bb4/wisdom-temp.webp 200w,\n/static/16148bca642b5b4ffc145e9425c6220d/28d7d/wisdom-temp.webp 400w,\n/static/16148bca642b5b4ffc145e9425c6220d/9fbef/wisdom-temp.webp 800w,\n/static/16148bca642b5b4ffc145e9425c6220d/235ac/wisdom-temp.webp 1200w,\n/static/16148bca642b5b4ffc145e9425c6220d/0d529/wisdom-temp.webp 1600w,\n/static/16148bca642b5b4ffc145e9425c6220d/99503/wisdom-temp.webp 2400w,\n/static/16148bca642b5b4ffc145e9425c6220d/4db61/wisdom-temp.webp 5184w","sizes":"(max-width: 800px) 100vw, 800px","originalImg":"/static/16148bca642b5b4ffc145e9425c6220d/7949e/wisdom-temp.jpg","originalName":"wisdom-temp.jpg","presentationWidth":800,"presentationHeight":533}}}}},"next":{"fields":{"slug":"/blog/elegant-patterns-in-modern-javascript-ice-factory/","dmPostId":"bc38fb281731b8ed840afa4140e69a21"},"frontmatter":{"title":"Elegant patterns in modern JavaScript: Ice Factory","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEA//EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAFsHeLgKBP/xAAZEAACAwEAAAAAAAAAAAAAAAABAgADERP/2gAIAQEAAQUCrxZdyUo6YU2FRprE/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHxAAAgECBwAAAAAAAAAAAAAAAAERITECEBIiMkGC/9oACAEBAAY/At3bMUck7QV0ryXJiuX/xAAaEAEBAQADAQAAAAAAAAAAAAABEQAhMUGB/9oACAEBAAE/IefCSAepihHgcMHuL03raqrkNivdTwB83//aAAwDAQACAAMAAAAQEO//xAAWEQEBAQAAAAAAAAAAAAAAAAAAESH/2gAIAQMBAT8QyI//xAAXEQEAAwAAAAAAAAAAAAAAAAAAARFB/9oACAECAQE/ENXD/8QAHhABAAICAgMBAAAAAAAAAAAAAQARIUFRcWGBwfD/2gAIAQEAAT8Qo4QiryNRWAIe5oNnMUDsMj96hOqJW+K9aiaDN1yxLbDVH5P/2Q==","tracedSVG":"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='400' height='267' viewBox='0 0 400 267' version='1'%3e%3cpath d='M0 28v28h4c3 0 4-1 4-2s1-2 5-2c6-1 19 1 19 3l1 1c6 0 3 15-3 19-2 2-7 13-5 13l1 7c0 6-3 15-5 15l-3 3c-3 2-9 3-10 1l-8-4a1239 1239 0 0 0 2 70c0-20 0-27 3-34l2-8v-2l1-4c0-4 2-6 6-6l2-1h8c10 1 14 1 24-2 9-2 11-3 10-12-3-17-2-39 2-39l3-4 6-5c13-7 13-8 12-14-1-4-2-6-5-8l-4-5c-1-2-1-2-3-2-4 1-5-1-5-10v-8h3c3 0 5-3 5-7l4-7c1-2-1-2-37-2H0v28M151 2l2 7c1 10 0 9 7 8 6 0 11 1 16 5 2 2 4 2 12 2h10l5 5 5 4-1 9-4 8c0 4-3 10-5 12l-3 3c-1 2-1 2 5 2a174 174 0 0 0 31-6c6 0 9-2 9-4 0-1 12-2 14 0h2l1 1c0 2 10 11 13 12l6 2a4652 4652 0 0 0 9 12c2 2 2 3 1 7l-1 6c0 5-5 12-13 16-4 2-5 4-6 6-1 6-6 16-9 20-3 3-3 3-8 3s-9-1-9-3l-2-3c-2-2-6-12-6-16l-1-5-18-3a288 288 0 0 1-18 0 1169 1169 0 0 0-9 73l-2 4-2 3c-5 4-5 12-1 14l3 1c1 1 1 0 1-2l1-8 1-5h41l42-1 2-4 1-3 2-4 2-4 1-2c0-6 2-6 15-6 12 0 15 1 14 5v2l2 5 3 4 5 2c3 3 6 4 8 4l3 1 18 1 16-1-2-1h2l4-1c2 0 2 0 2 2s-1 3-4 5c-4 2-5 3-4 4l-2 2c-3 0-5 5-4 6l-1 2c-2 1 3 5 9 7l6 3c2 2 6 4 10 4l6 2 3 2 1 2c0 2 1 3 3 1h1c1 1 5 2 7 1l2-15c0-11 0-14-1-13l-3 2c-3 0-10-6-8-7l1-2c-1-2 3-5 7-5h3v-76h-9l-12-1c-3-2-7-11-6-15 0-4 4-11 7-11a77 77 0 0 1 18-4c2 0 2-3 2-17V51h-2c-2 0-4 2-8 6l-5 5v2c1 1-4 11-5 11l-3-3-4-3c-5 0-7-8-4-14 3-5 3-7 3-16l1-4V24l2-3c1-2 2-3 4-3h5c2-1 8 1 9 4l3 2 3 1c1 1 1-2 1-12V0h-87a865 865 0 0 0-89 1l-37-1h-36v2M33 13l-5 2h-3l-9 1c-10 0-12 1-9 7l1 10c0 6 0 7 1 5s2-3 5 0c3 1 3 1 5-2l3-5c1-2 1-2 3 1l3 3c2 0 2 0 1 1v1c0 1 2 0 3-2l1-3v-1l3-4c1-3 3-5 4-5 2-1 1-5-1-8-3-4-3-4-6-1m265 12c-2 1-2 3-2 11 0 14 0 15 4 17l4 3c1 2 10 2 17-1 8-3 17-5 23-5 5 0 5 0 6-3 1-4 1-8-1-11-2-4-1-3-20-6-4 0-7-1-9-3-4-3-19-4-22-2M107 85v4c2 9 2 51 1 51l-2-3c-1-2-1-2-1 1l-1 3v-2c0-3-2-4-3-2l-4 2c-3 1-4 3-4 4l-5 7c-6 6-6 8-3 11 2 1 3 3 2 3l1 3c3 3 5 7 4 7h-4l-14-1-22-2c-11 0-12 0-13 5a3253 3253 0 0 1-3 21c1 8 0 9-5 10H7l-3-2-3-1v10c0 10 0 10 2 10s2 0 0 1l-2 1 3 1c3 2 8 1 6-1l3-1c2 1 3 0 3-1 0-4 1-5 4-4 2 0 3 0 4-2s1-2 3 2c1 4 3 5 3 3s5-7 7-7l3 2c2 2 2 2 0 4l-1 2 2 2c2 3 6-4 6-7v-3c2 0-5-3-8-3-6 0-2-4 4-5l5-1 11-1 16-2 10-2 3-1 5-1 12-2h8c1 0 2 2 2 9 2 24 3 24 27 25h9c-4 0-4-2-1-3l3-3 2-2c1 0 2-2 2-11 1-11 0-14-3-12-3 0-2-22 0-26l2-8 1-6c4-9-7-3-11 6-3 5-6 6-9 3-3-4-3-15 1-17 6-4 5-3 4-7l-2-10c-1-5-1-6-4-8-8-7-9-8-10-11l-1-3c-3 0-6-4-6-7l2-3c1-1 3-6 2-7h-1c-1 1-5-1-6-4-1-2-1-2-1 1 0 4 0 5-2 3s-3-6-2-8v-4h-4m7 56v11c-2 1 2 11 4 12 4 2 6-1 4-5l-2-6c0-4 0-4-1-2l-1 3v-3l-1-3-2-9-1-8v10m-13 5l-3 5-1 1c-2 0-1 12 1 16l2 6c-1 1 0 2 1 2l4 2 5 2c3 1 3 0 3-2l-3-34c0-2-3-3-3-1h-2s-2 0-4 3m81 64l-1 4c0 2 0 3-1 2l-2 2h-2c-2-2-8-2-8-1l-2 1-3 1c-2 3 0 4 5 5 6 0 8 5 4 7-2 1-2 1 0 1 8 0 12-7 12-18 0-5-1-6-2-4m-121 8c-1 2-5 3-5 1s-4-1-6 2c-4 4-4 6 0 5 3-1 3-1 3 1 0 3-2 4-5 3-3 0-3 0-4 2 0 2-3 3-3 1l-2-1-3-1c0-2-4-1-4 1 0 1-1 1-4-1l-4-1-2 1c-2 0-2 0 0 1l2 1 4 1c3 1 3 1 4-1l3-1-1 2-1 1 1 1c2-1 4 1 5 3h5c2 1 6 1 7-1 0-2 6-4 7-3l1-1c-1-2 0-3 2-1 1 2-1 4-5 4-2 0-5 4-2 4l1-1h4l3-1 1-2 1-3c0-3 3-5 4-3 1 1 7 0 7-1l-4-4-1 1h-4c-2 1-3 0-3-3s0-3 1-1l2 2c2 0 1-3-1-5l-1-2c0-3-1-3-3 0' fill='lightgray' fill-rule='evenodd'/%3e%3c/svg%3e","aspectRatio":1.6666666666666667,"src":"/static/e7e77ea2b45b4c2735891f7c561d6046/81b2d/ice-factory.jpg","srcSet":"/static/e7e77ea2b45b4c2735891f7c561d6046/de3a0/ice-factory.jpg 200w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/fcaec/ice-factory.jpg 400w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/81b2d/ice-factory.jpg 800w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/09873/ice-factory.jpg 1200w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/d0e89/ice-factory.jpg 1600w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/fe041/ice-factory.jpg 2000w","srcWebp":"/static/e7e77ea2b45b4c2735891f7c561d6046/9fbef/ice-factory.webp","srcSetWebp":"/static/e7e77ea2b45b4c2735891f7c561d6046/f9bb4/ice-factory.webp 200w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/28d7d/ice-factory.webp 400w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/9fbef/ice-factory.webp 800w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/235ac/ice-factory.webp 1200w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/0d529/ice-factory.webp 1600w,\n/static/e7e77ea2b45b4c2735891f7c561d6046/8e989/ice-factory.webp 2000w","sizes":"(max-width: 800px) 100vw, 800px","originalImg":"/static/e7e77ea2b45b4c2735891f7c561d6046/fe041/ice-factory.jpg","originalName":"ice-factory.jpg","presentationWidth":800,"presentationHeight":534}}}}}}}