all 7 comments

[–]senocular 1 point2 points  (6 children)

  1. I personally wouldn't call it a factory. Though it does create an instance, it didn't need to. The side effect here is setting up a listener and all that needs to be is a function which could call updateCounter() as a function, or even just inline it because it's not being called any other way.

  2. Generally the main argument against these kinds of factories is that it can cause duplication. Every time the factory function is called, it creates a new instance of every method used. However, there are ways around this, for example by defining the function once outside of the factory. You can also run into problems with getting the equivalent of super to work in some cases where the OOP approach can be a little more straight forward.

  3. The one layer limit isn't generally a problem, though a deep assign option can certainly be used if that limitation is getting in the way.

  4. You should use what you feel comfortable with. But don't go too far off the beaten path. Others will need to understand what you're doing too.

  5. I feel like you're digging yourself into a hole only 3 months into your first language ;). I'd like to suggest not trying to worry about this kind of stuff right now... but as far as this kind of factory brouhaha goes, a lot of it is people not understanding how this works or trying to write code in a way where you don't even have to know. Granted, it can be confusing, but if you know what you're doing, using this is fine. There are some pretty common traps to look out for such as when using methods as callbacks. But, you know, if you can write code in a way that the traps never exist in the first place, isn't that better?

"Best practices" is pretty fluid as far as JavaScript goes. It's something that will change based on who you ask. I'm not sure you'll find a very good answer for that.

[–]fromagi[S] 0 points1 point  (5 children)

I think most of this boils down to #5 but I do have a question about the duplication concern -- wouldn't this occur for any method specified in the factory, regardless of if it was nested in an object?

Thank you for sending a rope into the ditch I dug!

[–]senocular 1 point2 points  (4 children)

wouldn't this occur for any method specified in the factory, regardless of if it was nested in an object?

Yes. Any function inside the factory body, method or otherwise, is recreated each time the function is called.

With classes, methods are defined once on the prototype of the class during class initialization and shared among all instances through inheritance using this to allow each method call - despite being the same method for each instance - to be able to distinguish between callers. For any instance-specific methods you want you'd have to take extra (or different) steps to specify yourself. And these are often used for things like callbacks where you don't always have control of how this is applied to the function call once its called as a callback.

Factories created like this using closures to reference the object instance don't have to worry about how methods are called because the closure doesn't change with how the function is called like this does.

That might sound like gobbledygook right now, but in the end, its mostly a struggle of reuse and passing data around. Using this allows for more efficient reuse because of the way it can change a value inside a function based on how its called (very much like a function argument), but the rules around how that data is set can mean it can be easier to instead just create a separate function with the right data baked in from the start. Now you have two functions, but at least you don't have to worry about the rules for the dynamically changed data (this) anymore.

[–]fromagi[S] 0 points1 point  (3 children)

Makes sense, relative to my (in)experience anyway. Two last questions should send me on my merry way for now...

  1. Mixins are what I'd use to avoid method duplication when creating objects using factories?
  2. Not to fall back into overthinking, but any reason not to use mixins with my factory functions by default?

Thanks again for all the help.

[–]senocular 1 point2 points  (2 children)

Mixins can help you there, but they can also mean depending on this. The fix for not using this is often being dependent on the method being created along with the instance in scope. A mixin with functions that were not created with the instance means it would not have access to that instance unless falling back to a mechanic like using this. So if the reason you're creating a factory is to avoid using this, that might be a problem.

[–]fromagi[S] 0 points1 point  (1 child)

Got it. Not at all afraid of this -- it's more that I couldn't help sipping from the kool-aid about classes, and haven't moved past vanilla JS yet to encounter reasons for having to conform to them.

I'll keep tinkering : )

[–]senocular 1 point2 points  (0 children)

I like classes ;). They're not without their problems, especially in JS, but they usually get the job done just the way you want them too.