Live data from Hacker News

How to rewrite classes using closures in JavaScript

gaurangtandon.com

21–30 of 58 posts

Re: How to rewrite classes using closures in JavaScript

#22

There are private properties in classes class Foo { #ImPrivate = true; #meToo() { if(this.#ImPrivate) cantTouchThis(); } } new Foo().#meToo() === BOOM Also with using closures for "classes" takes up a whole lot more memory because new instances off all the closures are created for each instance of the class.

There are also getter (and setter) properties that can be backed by private fields:

get name() { return this.#name; }

Half of this article seems to be based on the author’s unawareness of JS class syntax.

Re: How to rewrite classes using closures in JavaScript

#26

What is the best and most modern way to write a module where you have public and private functions and data?

classes have the # prefix for private members and TS has the private keyword.

If you don’t want to go with classes, not exporting a value or a function from a module is almost the same. The rest can be done with closures.

Re: How to rewrite classes using closures in JavaScript

#27

There are private properties in classes class Foo { #ImPrivate = true; #meToo() { if(this.#ImPrivate) cantTouchThis(); } } new Foo().#meToo() === BOOM Also with using closures for "classes" takes up a whole lot more memory because new instances off all the closures are created for each instance of the class.

Private properties don't work with Proxy.

https://lea.verou.me/blog/2023/04/private-fields-considered-...

Quote:

> Private fields, proxies, pick one, you can’t have both.

Re: How to rewrite classes using closures in JavaScript

#28
There are several points in the article which are just plain wrong:

- no private properties (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...)

- no readonly properties: You can use a getter. Or define the property as non-writable, the syntax isn't nice but in my opinion it's still much nicer than what the article proposes.

Some of the points are just a matter of taste ("this" is awkward)

There's the implementation itself which forces you to use non-idiomatic code for no good reason or benefit (Class.init instead of new, just why? You can absolutely return a constructor function there while preserving everything else)

Doing what the article proposes also destroys the ability to do instanceof checks because the prototype of instances is not set (can be fixed), and inheritance is severely limited if you want to preserve any of the purported benefits. You might say that inheritance is actually not a good thing and so it's a feature, not a bug, but if that's your opinion why are you trying to mimic a class?

Re: How to rewrite classes using closures in JavaScript

#29

What is the best and most modern way to write a module where you have public and private functions and data?

classes have the # prefix for private members and TS has the private keyword. If you don’t want to go with classes, not exporting a value or a function from a module is almost the same. The rest can be done with closures.

Is there a “canonical” example of a module that is written well and uses what most would consider best practices?

When looking through npm modules, there still seems to be a variety of approaches.

Re: How to rewrite classes using closures in JavaScript

#30

What is the best and most modern way to write a module where you have public and private functions and data?

I'd say you might need to be more specific with your phrasing.

If you want replicate more class-like behavior (but without actual class/inheritance information):

- Some type of exported constructor function

- The function instantiates an instance of data internally that is possibly mutable (let vs const)

- That function returns an object/interface of functions that have access to that data by virtue of it being defined in a higher but accessible function scope

- All other private functions are simply not exported

Or you might mean singleton data:

- let or const data at the file/module scope level

- export functions to operate on the data

- Don't export functions you want to be private

The first is sort of reinventing a class instance, but if you are anti-inheritance for the most part (likely a good idea), then you can use a "kind" or "type" property on the returned constructed plain object if needed (TypeScript generics make this quite ergonomic to represent as well). So, you don't really need classes, but they have their uses and have familiar and comfortable syntax to programmers from other languages. You can use either and they are both accepted as idiomatic.

I usually still allow classes in codebases that I have some control over, but add a custom ESLint rule to ban extension unless with an ignore comment. This sort of encourages you to compose more like the functional/data approach, but allows you to still use instanceof since it's an actual class. It also means you're not creating a copy of all the method functions if you don't need to between instances.

There is a caveat that there is a class syntax:

method = () => {}

That auto-binds the method to this, creating that method copy for all. In this case you're encroaching on the plain object behaviour, again with a more familiar syntax.

So, I guess it's more messy than I thought reflecting on it. But you have some choices depending on what properties you'd like to encourage in your codebase.

Post reply on HN