5 ms·
This is Exhibit N for the "the class keyword is ruining Javascript" prosecution. If you want a "private variable" you just use a closure. let incrementer = (
by mkozlows 8y ago
This is Exhibit N for the "the class keyword is ruining Javascript" prosecution. If you want a "private variable" you just use a closure.
let incrementer = () => {
let x = 0;
return { value: () => x, increment: () => x++ };
};
It's like the OO people are determined to forget about the functional concepts that made JS great.
- Theodeus 8y agoI agree.
- sjroot 8y agoI was in the process of writing a reply that argued against this (mainly because it is not as readable as a class implementation), but I sort of agree with you as well. That said, considering how widespread JavaScript is at this point, I think it is in their best interest to cater to more than one programming style.
- josephg 8y ago> That said, considering how widespread JavaScript is at this point, I think it is in their best interest to cater to more than one programming style. No! Stop! Bolting 6 different programming paradigms into a language doesn’t make it easier to learn. It makes it harder, because every programmer who learns JavaScript needs to learn all of the tools of the language so they can read the code written by others. More language features / paradigms make JS less accessible. It is a terrible idea if your goal is to help people learn JS.
- sjroot 8y agoI agree with you, but if they are going to pick one paradigm to build new features for, it is certainly going to be OOP (for better or worse).
- ihuman 8y agoWhat are some other examples of the class keyword ruining Javascript?
- mkozlows 8y agoDecorators, which have to be added as a language concept because of classes, when otherwise higher-order functions would do what needs to be done.
- dmitriid 8y agoIt’s a non-fitting abstraction that’s poorly glued on top of a prototype-based language. As a result, uou have thongs like: - methods have no access to `this` on the instance of the class. Because they are defined on the prototype. As a result, you have to manually do a .bind(this) in your constructor for every method that needs access to `this` - meanwhile, if you define a class field: `field = () => this.foo` (with an arrow function), then you have no problems accessing the instance. Because of different scoping rules, binding etc. - and now there’s private fields. Which are just a hack to make them sorta kinda work
- 21 8y agoand now you are defining you whole class inside that return {}. Do you honestly find this more readable?
- keb_ 8y agoThis is similar to the Revealing Module Pattern in Learning JavaScript Design Patterns: https://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript https://addyosmani.com/resources/essentialjsdesignpatterns/b... I think it's perfectly readable, and it requires no more language hacks that obfuscate the JavaScript underlying `class` syntax sugar.
- eadmund 8y agoThis is why macros and a homoiconic language are such a good thing: you can add syntax sugar to have something which is both straightforwardly implemented and readable.
- lioeters 8y agoI often use a functional style as the OP's above, instead of classes, but I wonder about performance hit. Calling it often (like many "instances") and creating new functions every time seem less efficient that inheriting methods via prototype.
- Roboprog 8y agoIf I were to create 300 instances of something with actual func^H^H^H^H methods attached, rather than 3 instances, I would probably look into creating a prototype and coping with the perils of “this” usage, but otherwise, I’m not going to lose much sleep about it.
- Roboprog 8y agoYes, especially if the result is only used in a small number of nearby places, which is usually the case. My IDE can easily infer the properties of such objects, as well as display the JSDoc for such properties.
- mpweiher 8y agoThe JSR instruction is ruining assembly! I mean, you can just push the PC, then JMP to the address. And all that the pesky RTS instruction is doing is popping an address from the stack into the PC. Who needs it?!?
- te_chris 8y agoI went to a lunch with Douglas Crockford in London and was lucky enough to be seated next to him. Got to ask lots of questions about what he thought of new JS and he was unequivocal: All the new class shit is a hack by people determined to turn JS into C#. I agree with him. I don't get why people are wasting their time on private class members when features like pattern matching and the pipeline operator are making their way to the surface. Classes are the worst thing to happen to JS.
- orangecat 8y agoAll the new class shit is a hack by people determined to turn JS into C#. And that's not a bad thing. As long as JS is effectively mandatory for front end development, it should be approachable and familiar to the widest possible developer audience. I'm hoping for a WebAssembly future where you'll be able to pick your favorite esoteric functional language and have it transparently run in the browser. But until then, it's better for JS to look like C# than Haskell.
- vikingcaffiene 8y agoIf you are trying to evangelize for functional programming this is the wrong way to do it. “OO people” is not a thing. I can code in both functional and OO style and choose the one that best suits the scenario. Segregating into an us vs them or right vs wrong comes off as a bit smug and holier than thou. I’m sure that wasn’t your intent but just sayin.
- Roboprog 8y agoOn the one hand, I hear what you are saying, but on the other hand, I share the original poster’s frustration with what seems to be a culture that wants to force Simula 67 / C++ / Java as the last word on how everything MUST be done. He’s venting, not evangelizing. And his solution is a lot shorter and easier to follow than the drawn out OOP style version, even if I would have put the 2 functions in the returned object literal on their own lines.
- Roboprog 8y agoWell, it’s a little shorter if not a lot shorter
- vikingcaffiene 8y ago> a culture that wants to force Simula 67 / C++ / Java as the last word on how everything MUST be done. I mean OOP is very popular so maybe that's where you are getting that impression from? That said, you really could make the same argument for functional programming on HN. I see a _lot_ of commentary much like the parent comment that touts functional as the obviously better way to do things. It always kind of rubs me wrong. If you don't like OOP don't use it and vice versa. Personally I prefer functional programming and use it when I can but I don't think twice about switching it up to OOP if that's whats needed. Just think that it's important to bring all tools available to bear (<= spelling??) when you are attacking a problem. This job is hard enough without succumbing to dogmatic turf wars you know?
- rictic 8y agoThat means that for every incrementer you create, you've also got to allocate two additional functions: value and increment. They have to be distinct objects, because `incrementer().value === incrementer().value` must yield false. Debugging is also harder. When you're debugging and you find an incrementer somewhere else in your program (maybe somewhere unexpected), how do you know what kind of thing you have? All you can tell is that it's got a value and an increment method, so you've got to do a bunch of grepping over your source to find where it comes from. If it were a class instance you could ask instance.constructor.name to find out that it's an Incrementer, so you can grep for `class Incrementer`. Yes, lambda can do everything, which is really cool to learn! But lambda isn't the ultimate. More specialized tools often carry benefits.
- strainer 8y agoComparing these function references: `a_inc_instance.value === b_inc_instance.value` is true in javascript when the function `value` is a class method. In the closure/factory created version it is false - each function `value` is a different instance with a different reference. That will involve unnecessary duplication in the interpreter, but also allows for the function to be optimised for its state (monomorphic etc) which can be significant when more than a simple example `x++` operation is involved. So the class version does entail less memory usage, but the closure permits more JIT optimisation. > If it were a class instance you could ask instance.constructor.name to find out that it's an Incrementer, so you can grep for `class Incrementer`. Im not sure how much extra help that kind of thing is, we might instead grep for `symbol\s*=` to find where a symbol was assigned whether it had a .constructor.name property or not. I can see it is a general advantage of having more types, to have summary information besides the names.
- marmada 8y agoBut, that's so much more complicated then just having a private variable.