Hacker News new | past | comments | ask | show | jobs | submit login

I don't understand why people are so hyped about OOP syntactic sugar when JavaScript could already do those ages ago. For example: the class keyword. JavaScript could already do classes via factory functions (return an object with associated methods), and factory functions are strictly more powerful than classes because you can declare freestanding variables inside.

And here's the kicker: The freestanding variables that you do declare inside a factory function, those are naturally private fields. You can expose it to the outside world via method closures, but no one else can reach in and modify it directly. Classes can't do that. Functions could. But the general sentiment is to embrace classes and throw factory functions to the wayside, and as a result you need extra effort like implementing private fields for classes when JavaScript functions can already do the same thing.




Because syntactic sugar matters. var x = (function(){})() is just not readable, but it is error prone. The same goes for assigning to __proto__. IMO, the class keyword is a step forward. However, adding # to a variable looks like a step backward. How long before we have this.%x, to mark x "protected"? Or get x() {...} vs set #x()?


Factory functions don't mean using the (admittedly ugly) IIFE syntax or accessing __proto__ fields. This is an example of factory function

    function NewObj(n) {
        let myPublicInt = n;
        let myPrivateInt = 0;

        function privateIncrement() { myPrivateInt++; }

        function incrementPrivateInt() { privateIncrement(); }

        function printPrivateInt() { console.log(myPrivateInt); }

        return {
            myPublicInt,
            incrementPrivateInt,
            printPrivateInt,
        };
    }

    let obj = NewObj(5);
    console.log(obj.myPublicInt); // 5, because myPublicInt is a public field
    console.log(obj.myPrivateInt); // undefined, because myPrivateInt is a private field
    // obj.privateIncrement(); // exception, because privateIncrement is a private method
    obj.printPrivateInt(); // 0
    obj.incrementPrivateInt();
    obj.printPrivateInt(); // 1


so..... how do you know to optimize this as a factory function / "class" in your JS runtime with reusable instructions that just use an instance's scope in order to get good performance and memory usage.... When all that's being spat out is a JS object, that the user could very well modify in the next instruction, 30 instructions time, or conditionally based on some other checks?

And it's still a pretty ugly way of defining a class like object without the syntactics.


But an object constructed from a class still has all the optimisation problems you just mentioned. It’s just syntactic sugar. The optimiser generates invariants which, if invalidated, makes you fall back to a slow path.


The syntactic sugar is something the optimiser is aware of and isn't just a "do this in a more pretty/stylised way" for the developer, it conveys an intent that this is a construct that can be optimized with a certain level of confidence that you can't get from objects that "look like a duck and quack like a duck" if you squint a little.

And if anything happens that does "deoptimize" it, then if we know the "base" is definitely a class, the paths to handle the "deoptimization" can make better decisions and be able to avoid scrapping everything and falling back to the slow path.


JavaScript engines like V8 can already do exactly as you said through hidden classes based on source code position and have been doing so for a long time. I haven't read any evidence that classes are actually better optimized, even if it's often argued as the reason for why classes are better.


"var x = (function(){})() is just not readable, but it is error prone."

How so? I have no trouble reading that, it's certainly clearer than most of the c++ templates I've seen, and error prone? For example?


It's a bit apples and oranges. That declaration doesn't have the power of a C++ template. A C++ class is much simpler.

One of the problems of the style is that you can't easily split it up. Another one is that it allows you to redeclare/reassign x. A third one is that it doesn't tell the reader what it's doing. You'd have to look carefully to find that out. And then there's the "extends" functions, which everyone implements slightly differently. So, for me, the "class" keyword is a positive change that helps overcome JavaScript's dynamic nature a bit.


const x = ... it's usual to read code to understand it "helps overcome JavaScript's dynamic nature", you say that like it's a good thing


Weren't class and const introduced in the same version?

> like it's a good thing

I think so. If you have full control over your own code, and you write in e.g. TypeScript, you don't need it. Otherwise, it can prevent errors that take forever to debug.


The utility of const does nothing to support adding classes to javascript.

TypeScript, also unnecessary and often just a pita.

I've written very much javascript and have never had a bug that took "forever to debug'.

Programmers who like classes, and type-checking, and all the other syntactic sugar should, imo, just use languages that support such things and leave javascript alone.

I learned a lot about programming from the SICP when it first came out. I appreciate and use the good things Scheme inspired in javascript. And with very rare exceptions, such as const, let, and enhancements to builtin objects such as arrays, I still use vanilla js. I create new objects using factory functions and have zero use for classes.

However adding Map, Set, and similar objects to what is essentially the javascript library is fine with me as they do not impact the core syntax of js.


In mid-2000s Microsoft (of all orgs) was actually very opposed to the idea of bringing C++/Java-like classes into Javascript because they have quite an impedance mismatch with prototype-based nature of JS.

I'd say, they were right.


And then MS invented Typescript and it was all classes onward...

I don't really get it either, and I am saying this as someone who codes in both JS and Java. While thinking in OOP concepts comes naturally for me, I found the prototype/function based approach of JS a breeze of fresh air.

I guess the turning point was when JS migrated to the backend and more complex business logic was written in JS. As long as you are basically rendering view state or filtering data, traditional JS is much easier. But write the business logic of some enterprise app, and you want to use the OOP paradigms.


In my opinion, the code was very difficult to read and even harder to understand for !expert javascript devs and even for experts.

For example, I did, what every decent JS developer back then did: you build yet another library ("helper library"), that just abstract these creations away.

So what else is the Class syntax? A helper.

I felt I was one of the very, very rare JS devs, who read "Secrets of a JS Ninja" from John Resig, the jQuery legend, top to bottom multiple times. Afterwards I build very cool stuff, however folks did not understand it with their normale knowledge of JS. It blew me away, that you could do stuff like Function.toString() in combination with RegEx and New Function(). I was awesome, that I could do, what the C# and Java guys could do. I just took a lot more code to achieve. Fast forward 10 years.

I am extremely glad, that TypeScript came a long. It makes collaboration so much more meaningful.

I still love the JavaScript ECMA5 stuff, however the tradeoff was too big. It is like staying with C instead of Python, Java, or DSLs.

Even "You might not need jQuery" ended up being pointless in regards to readability. Why write 20 lines of code, when you can put it in one line? Paradoxically Resig's jQuery had to do a lot of complex stuff to achieve the beauty of $(). So why not simply write Class?

Just my opinion.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: