Javascript classes: state management

Tobias Uhlig
Feb 20, 2020 · 4 min read

[UPDATE] Version 2 of this article is now available

In case you are working with the ES6+ class system, you most likely want to use configs (properties) for your own classes. Since the class system is still lacking to define these inline, you could use the constructor:

You will most likely notice right away, that this approach is not really helpful, since you have no change listeners for your class configs. Defining the properties via get & set can help with this:

Both class definitions are pretty similar, but the 2nd one allows us to use myInstance.a = 2; for automatically triggering the setter. As a design pattern, saving the content of each property inside a underscore prefixed version does make sense (e.g. a => _a). You could add more logic into each setter, but as soon as you want to extend your own classes again, this will cause problems. So calling new methods which you can extend or override makes more sense:

Passing the new & the old value makes a lot of sense. As a design pattern, I recommend to use method names like afterSetMyConfig(). In case you want to extend your class now, you can override afterSetA and use the superclass call (super.afterSetA(value, oldValue);) as needed.

In case you are using the neo.mjs framework, you can shorten this code quite a bit:

applyClassConfig will generate something similar to the previous version, with the difference that you can change the default values for your properties more easily when extending classes.

Chicken or egg?

You might have noticed that afterSetA() is using this.b internally. You could flip the order of a_ & b_ inside the getConfig() method to change the order in which the configs do get applied. Since afterSetB() is using this.a internally, we ended up with a circular reference, so we can not solve this issue just using the config order. In neo.mjs, i solved it like this:

=> https://github.com/neomjs/neo/blob/dev/src/Neo.mjs#L540

The important part is that in case not all configs got applied yet, the afterSet methods will not get executed but get stored inside an afterSetQueue instead. Once all configs did get applied, the afterSetQueue will get processed and this ensures that circular references when creating classes / instances are no longer a problem.

How to define an instance state?

I have seen several different approaches and personally prefer to see a state as a permutation of class configs (properties).

After creating an instance (you can use “new” if not working with the neo.mjs class system), you can change each config directly as an assignment, triggering the setter:

In our simple TestClass example, a state could be:
{a:1, b:2}
and another one could be:
{a:2, b:3}

To switch from the initial state to the second one, you could use:

Chicken or egg version 2

Although you can flip the order of the configs, we are still dealing with our circular dependency inside the afterSet methods, so using Object.assign() might cause issues.

The solution is to create a set() method, which will use the afterSetQueue for dynamic changes as well:

You can define the logic like this, in case you don’t want to use neo.mjs:
https://github.com/neomjs/neo/blob/dev/src/core/Base.mjs

A fully working test could look like this one:

https://github.com/neomjs/neo/blob/dev/test/siesta/tests/ClassSystem.mjs

Running it will generate the following results:

https://neomjs.github.io/pages/node_modules/neo.mjs/test/siesta/index.html#tests/ClassSystem.mjs

This is it for now, happy coding & best regards!

P.S.: Feedback & questions are welcome!

The Startup

Get smarter at building your thing. Join The Startup’s +788K followers.

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Tobias Uhlig

Written by

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +788K followers.

Tobias Uhlig

Written by

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +788K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store