A state container in the wild. I tend to avoid classes whenever possible in Javascript as I usually prefer a functional style over an object oriented one. But one thing that objects do really well is state encapsulation. In this article, I’m going to argue for using the function constructor pattern without as the preferred approach for encapsulating state. This was inspired by the widespread criticism of the private fields TC39 proposal on . this Reddit I’ll be talking about how to encapsulate state: With the ES2015 keyword, class With simple functions and object literals, Without using and having private fields this At the end of the article, I have a waiting for you, demonstrating composition with this pattern. You might like this if you like ! bonus React Hooks Using ES2015 classes This is probably the most popular option as of 2019, and I think the following should be pretty easy to understand: class MyObj1 {constructor(initVal) {this.myVal = initVal} set(x) {this.myVal = x}} Once instantiated: const x = new MyObj1(0) You can set the value of with either: myVal x.set(2) Or: x.myVal = 2 Similarly, you can access the field directly: console.log(x.myVal) // output: 2 This all seems great and the syntax looks very inviting to people familiar with other OOP languages, but there are significant flaws with this approach. No private fields The next time that is something you didn’t expect, it’s not so easy to figure out where, when, and how it was changed. your object field It’s relatively straight-forward, but the lack of private fields make this implementation potentially dangerous. The whole point of state encapsulation is that you want to control what can and cannot alter the state (and how they do it). But in this case, anyone (or any part of the program) can set to anything. The next time that is something you didn’t expect, it’s not so easy to figure out where, when, and how it was changed. x.myVal myVal If you had private fields, however, you can have control over the behaviour of setting the variable via the method on your object. set Extra mental overhead and API surface area Understanding of the ES2015 class syntax is extra mental overhead for developers. There are on-going proposals to augment this with (the syntax of which is still and uncertain). public and private fields contentious These proposals make it even more difficult for beginners and even seasoned developers (who don’t actively track TC39 proposals) to use classes in practice. Classical inheritance On top of that, the nature of the syntax (via the keyword) encourages inheritance over composition and incorrectly suggests the traditional classical inheritance pattern. extends Some prior art regarding class and classical inheritance issues with Javascript: by Eric Elliott 10 Interview Questions Every Javascript Developer Should Know by FunFunFunction Composition Over Inheritance See also Douglas Crockford’s talk linked at the bottom of this article Using simple functions and objects i.e. “class-free” object oriented programming So if we’re not using the keyword, what should we be using? class Simple functions and objects! These are the basic building blocks that even the most junior developers are familiar with. All we’re doing is writing a function that returns an object literal; not exactly rocket science. This is how we declare our function: const MyObj2 = initVal => {return {myVal: initVal,set: function(x) {this.myVal = x}}} Notice that you didn’t need to learn about or at all. It’s just a function that returns an object. We create one like this: class constructor const x = MyObj2(0) We didn’t even need to use the keyword because we’re not going to be modifying any prototypes (which is a bit of a code smell in 2019, IMHO). It’s simply a function that returns an object. new Similar to the ES2015 class approach, we can set the value with: x.set(2) Or: x.myVal = 2 This approach still has all the issues of not having private fields, but at least we’re no longer in a different paradigm. I argue that this itself is a big improvement over the ES2015 class approach because there really is nothing new to learn here. It’s just basic Javascript: Functions and Object Literals Not using the `this` keyword The keyword in Javascript confuses both new and old programmers alike. In older code, you might see being assigned to or . And a quick Google search will reveal numerous articles attempting to explain how the keyword works in Javascript. this this self that this I’m not going to discuss why avoiding the keyword is preferable, that is an exercise left to the reader since much has already been written about it. Instead, allow me to explain the benefits of an alternate approach. this If we simply use closures, we can define an object-creating function like this: const MyObj3 = initVal => {let myVal = initValreturn {get: function() {return myVal},set: function(val) {myVal = val}}} Just like the approach above, we can use it to create an object like this: const x = MyObj3(0) The variable is essentially private, which means we can no longer access it using like in the other implementations above. Instead we have to call the getter function: myVal x.myVal x.get() In some ways, this is a drawback of this approach, but it can also be considered a benefit when you consider the power and explicitness that it gives you. Closures enable a strong contract The variable is conceptually “saved” inside the object returned from the function thanks to Javascript closures. This means that we can set the value with the setter method (i.e. ), but attempting to directly change the field (i.e. ) won’t do anything. x.set(2) x.myVal = 2 The greatest part of having these explicit setters and getters is that the object now has a strong contract/interface with the outside world. The state is fully encapsulated and the only ways in and out of the object is through the setters and getters. What about prototypes? Note that I completely skipped over using prototypes and prototypal inheritance in this conversation. This was deliberate, because modifying prototypes as a pattern has become less and less common in recent years. And even Douglas Crockford (someone who was previously a proponent of prototypal inheritance) is now recommending “class-free” object oriented programming (i.e. the pattern discussed above). What about performance? One drawback about using closures is the issue of performance. While there doesn’t seem to be any when creating an object, method calls on the object using closures were about . difference 80% slower Admittedly, I didn’t look into this too much, but since the different results are in the same order of magnitude, it might be a case of premature optimization to be too concerned about this. If you are making millions of method calls per second and performance really matters to you, then it’s a judgement call as to whether or not the sacrifice is worth it for your specific use-case. Simplicity matters Personally, I think a smaller API surface area is a good thing for the community as it means less confusion for beginners and more standardized patterns for getting things done. You don’t have to use all features of a language, and you don’t get extra brownie points for doing so. Sometimes, less is more. Why add classes when simple functions and plain Javascript objects will do? An understanding of closures is already required when you’re working with functions in Javascript. Interestingly, Redux uses this pattern in their . createStore function For more on this approach, check out Douglas Crockford’s talk here: See discussion on inheritance and the function pattern at 41:55. He adds for further safety, which I would recommend as well. The entire talk is worth watching, but pay special attention to the part where he starts talking about classes at 41:55 onwards. Object.freeze As we go forward in 2019, let’s commit to thinking critically about how we code and the language features we are using. Sometimes it might benefit us to use less rather than more. For the full code, check out the repo here: _Examples of state encapsulation in Javascript. Contribute to adrianmcli/js-state-encapsulation development by creating…_github.com adrianmcli/js-state-encapsulation Bonus: A counter example with composition! Warning!!! This might remind you of :) React Hooks