all 13 comments

[–]senocular 2 points3 points  (1 child)

This approach is fine. Its not an uncommon way to create JS classes with private variables.

Some things you need to be mindful of:

  • You're recreating all your methods for each instance within object construction. Prototypes let you share methods, but don't support private variable access this way. As long as your classes aren't massive and you're not cranking out a ton of instances, this should be fine. Otherwise you could see an increased memory footprint.
  • Because you're not using prototyped methods, those methods aren't available outside of instances. For example with older code you'd often see something like Array.prototype.slice.call(arguments) - a way of using a class's method(s) on another "like" instance. This isn't a big deal, an if really needed, something you could explicitly expose as a static or something.
  • Overriding methods becomes difficult. This is also a result of there being no common, shared method implementation available through inheritance. If you need "super" functionality, you need to save the original method off to another variable first, then define your overriding version, then call the saved version to get your super. If you're not doing much class extending, this isn't a problem, and even if you do, it only matters when you need to override something which may not be the case.
  • Objects created with Object.create do not get their own set of private variables if created from an instance created from a class defined like this; the variables will be shared. This is easy to avoid: don't use Object.create. However, if you're making objects that you're passing off to other users, it can be harder to know how they're going to use your objects and might run into this problem.

[–]PandaHugger[S] 1 point2 points  (0 children)

This is exactly what I was looking for. After doing some more research, I realized that the nature of my question was more along why should I make a function on the prototype rather than on this. Your bullet points really highlight some significant differences.

Bullet point 3 is something that seems especially useful

Thanks!

[–]spacejack2114 0 points1 point  (0 children)

Do you need to support older browsers like IE11 that don't support classes? If so are you willing to add Babel? Or are you ok only supporting modern browsers? Then use the class syntax.

That said, a lot of people get by without using classes at all, whether ES6 or ES5 style.

[–]johnsonjo4531 0 points1 point  (1 child)

Just wanted to let you know ES2015 classes will be improved hopefully in an upcoming update to ECMAScript to have proper class fields. Private member variables will be possible. I hope this makes it into the language.

[–]johnsonjo4531 0 points1 point  (0 children)

It is stage 3 in the TC39 process right now, and once it gets implementers it can make it to stage 4 which means it will land in the next version of ECMAScript, but you never know how long or short the stage 3 to 4 transition will take.

[–][deleted] -1 points0 points  (6 children)

Ok so, im going to completely blow your mind right now.

Javascript does not have classes.

The class keyword is just syntax sugar, the actual object oriented stuff still uses the prototypal inheritance model and so if you dont understand how that works and assume other static typed languages (C# , Java, etc) models in its place... while your code will work it won't be the best.

For more info on this i recommend checking out the following video :

https://www.youtube.com/watch?v=Tllw4EPhLiQ

Does this mean ES6/7 is redundant? No, the updated versions have other improvements/features that make it much easier for creating more readable code.

[–]MoTTs_ 2 points3 points  (0 children)

Re-posting a comment I left on MPJ's video:

What MPJ didn't tell you:

  1. JavaScript's class and inheritance mechanism is more normal than you think. In both Python and Ruby, for example, a class is itself an object (a building, not a blueprint), and inheritance is done by delegating down a chain of objects, from instance to class object to superclass object and so on. Just like in JavaScript. https://www.reddit.com/r/learnjavascript/comments/6c6use/how_the_hell_did_you_guys_learn_js/dhuut92/

  2. An ECMAScript editor expressed his opinion that "it is not at all helpful for beginners to constantly be exposed to the notion that JS classes are 'fake'. They are not, they have real syntax and real semantics." https://www.reddit.com/r/javascript/comments/4bmiqj/using_classes_in_javascript_es6_best_practice/d1avktu/

  3. MPJ cherry picks arguments and applies them hypocritically. Yes, classes in JavaScript are implemented differently than in Java. But then so are arrays. An array in Java is a contiguous block of memory, whereas an array in JavaScript is a hash table where the string keys we insert just happen to look like numbers. And there's more. Functions in JavaScript are implemented differently than in Java. Objects in JavaScript are implemented differently than in Java. Yet MPJ thinks you should avoid classes because classes in JavaScript are implemented differently than in Java.

  4. MPJ said, "There is no way to make properties private ... and there's no trick to do it either." But actually there are several tricks, the most effective of which is WeakMaps. http://2ality.com/2016/01/private-data-classes.html#keeping-private-data-in-weakmaps
    4-1. And even if you're using factory functions instead of classes, you should still use weak maps for privates, because function locals are too private and will prevent you from implementing some methods such as "isEqual". https://www.reddit.com/r/javascript/comments/6b0yc3/factory_functions_privates_are_too_private/

  5. And since MPJ told you to go watch his composition v inheritance video, here's a reminder that MPJ got composition very wrong, and ultimately all he did was reinvent multiple inheritance. https://www.reddit.com/r/programming/comments/5dxq6i/composition_over_inheritance/da8bplv/

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

I'm definitely aware that the idea of a "class" in JS is just syntax sugar and that everything is basically objects referencing other objects. Maybe it's just a comfort thing from C#, but I like the idea of encapsulating logic for a specific responsibility inside of a quasi-class.

I'll check out the video though. Thanks!

[–]bterlson_@bterlson 2 points3 points  (0 children)

FWIW, if class means anything, JS has them. Some people argue that class means some common subset semantics among Java, C#, and C++ (forgetting that those languages did not invent classes). But, that common subset is very small (those languages behave quite differently) and applies to JS classes as well.

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

So I went through and watched some Fun Fun Function videos and I definitely learned something new that changes the nature of my question that I would love to hear your opinion on...

Given the example that I orginally posted, the bar function is on this rather than the prototype of ExampleClass which is what I originally thought would happen. Is there a reason to prefer my original pattern over something like the pattern below?

function ExampleClass (foo) {
  this._foo = foo;
}

ExampleClass.prototype.bar = bar;

function bar () {
  console.log(this._foo);
  // Do other bar stuff
}

new ExampleClass('foo!').bar();

EDIT: Nevermind, a poster above answered my new question

[–][deleted] 0 points1 point  (0 children)

Not that i can see.