5 ms·
Yyyyyeah, classes in js are pretty bad full stop. For instance, passing a method as an argument will do awful things unless you bind it to a this first. Gross.
by migf 3y ago
Yyyyyeah, classes in js are pretty bad full stop. For instance, passing a method as an argument will do awful things unless you bind it to a this first. Gross.
Still, it's interesting to me that Proxy is more valuable to author than private member variables. Curious about some common use cases.
- eyelidlessness 3y agoProxy is commonly used to wrap reactive object values, which is the use case the author identified as an issue.
- graypegg 3y agoTotally agree. This is very much a symptom of JS’s class-ish syntactic sugar. Access modifiers have to be a runtime check, and be bolted onto an environment that was built around function scope being the only way control access. Using typescript to handle things like access modifiers at compile time makes everything much more predictable.
- dexwiz 3y agoDoesn’t typescript just transpile to closure based access control?
- afiori 3y agoClosures are a much better "class" primitive than JS classes
- nosianu 3y agoTypeScript's "private" is only for type checks. It is simply removed. You may also want to read what I wrote a few days ago already: https://news.ycombinator.com/item?id=35653653 https://news.ycombinator.com/item?id=35653653 TypeScript now supports both the ECMAScript #private - it has no choice in the matter, since it's in the language now - and their own development-time "private". It sounds messy but that's the fault of those who wanted it in the language, as runtime checks. I agree with the other comment, closures are far more powerful and flexible. I understand that this OOP stuff in JS was probably a nod to the many programmers in many companies already used to it, to make JS more palatable for them. It's easy to demand millions of people worldwide to adapt, but in business reality it does not work that way. So I grudgingly accept those new(er) things in JS as a business decision and necessity, for the huge crowd of people doing programming mostly just for the money, who had to write more and more code for the web that used to be run as installable software on Windows.
- dexwiz 3y agoEven without classes there are a ton of footguns involving ‘this’ and method scope. Fat arrow notation papered over a bunch of issues. But I have lost more than a few hours confused as to why changing between map and a loop completely broke/fix behavior. Or seen codebases absolutely peppered with unneeded ‘bind(this)’ like it would ward off evil. I had to spend some time studying before I really grokked it.
- pwdisswordfishc 3y ago> For instance, passing a method as an argument will do awful things unless you bind it to a this first. That was true long before classes arrived.
- mst 3y agoIt continues to sadden me that the implicit this injection happens only on direct invocation - let res = obj.method(arg); and let m = obj.method; let res = obj.method(arg); being different things seems like an unfortunate trade-off (though not knowing the full reasons it was chosen to be that way makes me wary of assuming it was the wrong decision overall). I've been known, for things where the object is e.g. a bag of components, to loop at construction time and replace all of my methods with pre-bound copies of themselves, but having to make a conscious decision as to whether I need to introduce that extra code (and work for the runtime per-instantiation) still makes me grumble to myself every time.
- llamaLord 3y agoCan you explain wrist you mean by those two examples being different things? Do you mean that 'res' evaluates to a different result in each? Or that when you call 'object.method()' vs calling 'm()' you would get a different 'this' context?
- mst 3y agoI completely messed up one of the examples, sorry. I meant the 'this' thing - a sibling comment to yours contains the correct code.
- majou 3y agolet m = obj.method let res = m(arg)
- mst 3y ago-facepalm- Thank you.
- imbnwa 3y ago>Yyyyyeah, classes in js are pretty bad full stop. For instance, passing a method as an argument will do awful things unless you bind it to a this first. Gross. One of the things that heavy use of JS frameworks will do is make you forget you can pass an object interface to represent continuations. The DOM spec defines the EventListener type, in TypeScript notation, as: `(event: Event) => void | { handleEvent(event: Event): void }` What does this type signature instruct us to think? That a function closure should reference objects in its scope, no need for `this` binding, or an object interface, appropriate to the domain of the deferred caller should be referred to and called (e.g. `handleEvent` in the case of DOM's EventTarget interface, but one could also imagine `{ onTimeout() : void }` if the spec authors were consistent, perhaps accepting a key to differentiate calls in the same vein as event types), also eliminating the need to bind `this`. The addition of `WeakMap`\`WeakSet` to the runtime eliminates the need for manual resource management. But React, the most popular JavaScript library (and its not alone in this), makes this pattern impossible: you can only pass functions to event listeners. So everyone then growls about `this` binding.