6 ms·
Classes are Expressions
- ravicious 11y agoWhat about private functions? For now I just add `_` in front of their names, but the code would look so much cleaner if I had some kind of a `private` keyword.
- Zikes 11y agoI don't see why this technique wouldn't also work for methods, especially with the addition of computed property names [1]. [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- braythwayt 11y agoThis technique absolutely works for methods. And again, this shows the elegance of having simple features that compose, rather than building a monolithic OO system.
- Animats 11y agoIn practice, that turns into far too many ways of defining classes in Javascript. There are at least four major approaches, and that was last year.
- braythwayt 11y agoIf you want something that isn't in the language, you build it yourself. If what you build becomes popular, in the fullness of time it gets built into the language as a full feature or as syntactic sugar. That's exactly how we got the class keyword, modules, everything. But if you choose the wrong thing, one day your choice is obsolete. That is a risk, and it's prudent consider the consequences carefully. If that troubles you, by all means write your code without any encapsulation, and wait for the language to acquire the feature in a few years. In the mean time, your code base will grow without that kind of encapsulation. Only you can determine whether this is a bad thing or not. YMMV, and all that. This is a very common problem to ponder, we end up arguing about whether you should be an early adopter, a main streeter, or a laggard. But really, the post isn't a screed in favour of using private properties, it's a suggestion that making classes out of first-class values in the language gives us the flexibility to build whatever we think we need. Private properties is a particularly simple example. Traits and mixins are also useful, but would take even more space to articulate. But the general point is still that making new things ("classes") out of the existing materials ("functions and prototypes") is a win in general.
- rmrfrmrf 11y agoThat's part of why I think CoffeeScript isn't going anywhere anytime soon.
- ravicious 11y agoSure thing, but could you show an example? Let's say we want the `rename` function be private, this is what I came up with: https://gist.github.com/ravicious/5412eebf8a1934ec7886 https://gist.github.com/ravicious/5412eebf8a1934ec7886 I don't particularly like this solution, because now I can't just write `this.rename()` in other Person functions. That's why I'd rather have a baked-in way to define private properties & functions instead of having to use (in my opinion) this weird syntax and later explain the whys and hows to other developers.
- braythwayt 11y agoWriting this[rename](...) instead of this.rename(...) is hardly onerous. Your solution mostly works, but a simpler one takes advantage of combining computed property keys and compact method syntax: https://gist.github.com/raganwald/18f8c179101cfd93c291 https://gist.github.com/raganwald/18f8c179101cfd93c291
- ravicious 11y agoOkay, now this certainly feels better than my example and is much more bulletproof than prefixing function names with `_`, thanks.
- mikegerwitz 11y agoYou wouldn't be able to simply; the same issues exist as in ES3 in this regard. (I wrote about them extensively years back here: http://mikegerwitz.com/papers/coope/coope.pdf. http://mikegerwitz.com/papers/coope/coope.pdf.)
- emehrkay 11y agoThis is cool, could this behavior be mimicked by doing: var name = 'name_' + Math.random() ; //assumed uniqueness
- braythwayt 11y agoYes, but you'll also want to use Object.defineProperty to ensure that the property is not enumerable. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... Symbol tosses that in "for free."
- greggman 11y agoI guess I need to be schooled by why not just use closures? var Person = function(first last) { this.fullName = function() { return first + " " + last; }; this.rename = function(newFirst, newLast) { first = newFirst; last = newLast; }; }; Problem solved, you can't access `first` and `last` outside the class. You might retort "they're bigger" or something but just like everything else in JS they just need the right people to concentrate on them and they'll likely get optimized. I don't get the relucatance to use the language's features rather than hacks (using naming standards and compilers to obfusticate names and then cross fingers) or other hacks (Symbol). Really? You Really want me to write code using Symbol? That's going to be awesome in the debugger. Let's add a watch to "weke30o304_first". Refresh, of shit it's now "gtgrf40r3fe_first", my watches all broke (T_T) It also makes me sad the `class` spec didn't take that into account so you could use a closure with a `class`.
- braythwayt 11y ago> I don't get the relucatance to use the language's features rather than hacks Symbol is a language feature. As is accessing a property with `[` and `]`. Using the language's features as they were designed is not a hack. And I think we may see your browser's tooling improve when it natively supports ECMAScript 2015, instead of whatever is transpiled today. Now: Why do you think that properties named by symbols have this special property of being non-enumerable by default? Do you think it is just a coïncidence that it is useful for making a pseudo-private property? I do not think this particular pattern is a "hack," I think it is one of the use cases that were considered when designing symbols in the first place. But returning to the purpose of the article, whatever you or I may think of the performance of using closures to create private data, your pattern again supports the article's thesis: By making classes out of functions, objects, and prototypes, we can use the features of the language to extend a class's semantics. If there was a full-featured monolithic class system like Ruby, we might find that the scoping for methods is not like the scoping for lambdas, and thus we can't just use a closure when we want one. Your proposed solution leverages the exact same property of JavaScript as TFA.
- greggman 11y ago
- spankalee 11y agoI know this might be an unpopular view here, but declarative(ish) constructs like class give a little hope that programs will be more statically analyzable so that we can get nice things like static type checking and warnings, code completion, optimizing compilers, etc. These types of imperative patterns make life extremely hard on tools, which now need to add in unreliable things like escape analysis to be able determine which classes are visible. Modules will help a little with explicit exports, so that the importing modules have some hope of tooling, but analysis within a module would suffer.
- keithwhor 11y agoJust looks like more JavaScript antipatterns, this time with some ES6 flavour. We know how to "solve" the problem of encapsulation with JavaScript. It's not with closures, Symbols, or some other arbitrary hack. We do it by enforcing specific idioms that only require a developer to recognize intent instead of learning 80 different ways to do the same thing. You simply put a single or double underscore in front of the property name. I read what I thought was a clever anecdote by another developer the other day, that the underscore in "obj._varname" indicates "here be dragons." It's an extremely simple idiom to teach new JavaScript developers. I get it, JavaScript is robust. So you can do fun things like this! These are great experiments. But really, what are you accomplishing? You've now just thrown in a closure and a bunch of lines of code (defining your symbols, etc.) that any developer new to your codebase is going to look at like "... what the... what is going on here?" You can solve the problem easily with one character. Consistency. Convention. Creating useful, easy-to-understand, repeatable idioms. That's what we should be focusing on.
- wvenable 11y agoYou can't check that the convention is being broken which makes refactoring more difficult. There will always be a temptation for some developers in some situations to mess with the internal state of objects.
- Jare 11y agoDevelopers willing to make messes in the code must be identified ASAP, and the "_" acts as an easy to see red flag.
- woah 11y agoIn general, js is more about good practices and craftsmanship, and less about finding ways for the language to force people to do things.
- wvenable 11y agoI find this argument to be lacking; if you're using good practices and craftsmanship then nothing is being forced on you as you would not encounter an error for doing something improper. I prefer to mark up my code as private/protected/public for my own purposes both as built-in documentation and to have one less thing to think about after it's done. Plus underscores are ugly.