Live data from Hacker News

Public and private class fields

developers.google.com

91–100 of 112 posts

Re: Public and private class fields

#91

Earlier quoted context omitted.

Implementing support is not the same thing as turning a feature on by default. The TC39 process states that limited spec changes may still occur after a stage 3 proposal. Until a proposal reaches stage 4, it should be hidden behind a settings flag. This helps us prevent situations like flexbox, where users code against a specification and find out later that their code has broken in subtle ways. > as well as implemen…

Fixed the autocorrect error. It is super meaningful - it helps identify potential issues in real world use-cases and it creates effectively a "market" of people already using the feature who want to be able to use it without transpiling. It's also pretty rare that the implementation changes meaningfully after implementation into Babel from around stage 2.

I should have used a more descriptive term than meaningless.

Transpiler implementations do not count as hard restrictions on whether or not a proposal can change in the future. They're allowed to do whatever they want -- the fact that they create demand is very useful, but should not be seen as a restriction on whether or not the standard can evolve past that point.

"It's also pretty rare" is exactly the problem. They can change. When browsers ship a non-standardized behavior that's on by default, they are effectively cementing it. It is very hard to correct a broken implementation that is live, in the wild, on normal sites. The fact that these changes are rare doesn't make it less important to follow the established process. Stage 3 is one last safety check before the feature gets turned on for everyone.

What is the point of having a stage 3, if browser makers treat it as equivalent to stage 4?

Re: Public and private class fields

#92

Earlier quoted context omitted.

I would be interesting to see exactly how much stuff is copied by the various implementations in such cases. There are obviously some stack or other data frames that have to be captured somehow, but the code itself should in principle be something the VM makes a single copy of with references to in each object using it as a property. (Internally within a Function type reference, separate trackers for the instructions…

Normally it could be effectively optimised away and just treated as an extra argument. But it's also required by the spec that `foo().method !== foo().method` when returning new functions from a closure in `foo`, so the function has to be wrapped and a new structure allocated each time to differentiate.

Thanks. I suspect the internals of “===“ in this case could look for the presence of a closure data pointer on a Function or some such hack.

Anyway, I’d probably use an actual prototype on something (with “methods” and) hundreds of instances, but otherwise, I’m not too worried about just using closures and object literals.

Re: Public and private class fields

#93
post #42

Earlier quoted context omitted.

Getters/setters are useful. E.g. maybe you had a class 'Box' with a field 'area'. Later you added fields 'width' and 'height'. What are you going to do? Change 'area' to 'getArea()' and break the API? Write extra code to ensure that you update area every time you change width or height? Or write a getter that returns width*height? I'd say getter is the cleanest option in many cases.

"Breaking the API" is what we call "refactoring" in the (extremely common) case where your code is only used in a single project, and not part of a reusable library. And yeah, if you radically rework how you make your boxes work, that's a good time to do a refactor. But there's no reason to anticipatorily add in a bunch of complexity so that you don't have to convert a value to a property at some hypothetical future…

Maybe they're not all that useful for small projects, but they're still useful for open source libraries.

And the area example use-case holds if it was a read-only property.

Re: Public and private class fields

#94
post #42

First, like the other commenters, I'm not in love with the perlish # syntax. I'm not sure why it was wise/necessary to add a previously illegal character as a prefix, rather than adding a "private" keyword, but I'm sure there's some reason. Second, the example affords an opportunity to rant about a pet peeve of mine. "Now ask yourself, how would you implement this class in JavaScript?" I wouldn't. Listen folks: unles…

Getters/setters are useful. E.g. maybe you had a class 'Box' with a field 'area'. Later you added fields 'width' and 'height'. What are you going to do? Change 'area' to 'getArea()' and break the API? Write extra code to ensure that you update area every time you change width or height? Or write a getter that returns width*height? I'd say getter is the cleanest option in many cases.

Any one of the proposed alternatives is better than altering the contract of the behaviour of `area`, which is what you're doing if you hide it behind a getter.

Re: Public and private class fields

#95

Why? I feel like the person who proposed this is relatively young and newer to coding. The reason why i say this is the functionality he is proposing can already be done using one of the myriad of JavaScript design patterns - https://addyosmani.com/resources/essentialjsdesignpatterns/b... It can already be done in a clean and easy way with a an anonymous self executing function - (function(){//EVERYTHING HERE IS PRIV…

Making classes (or equivalent) in the way you propose - ie "make use of closures for private instance fields" - does not work well. It requires allocating a new copy of each of the class's methods every time the class is instantisted, working around the prototype system. If we're arguing about crappy misuse/abuse of JS and "doing it wrong", surely this is far worse?

what i was demonstrating by showing that design pattern is that there is already an easier and clean way to do private variables and scopes.

BUT if you want to talk about its speed and efficiency here we go:

It very intentionally trades memory space for faster variable resolution.

plz read this article - https://www.toptal.com/javascript/javascript-prototypes-scop...

he has some test code at the end that compares the speed of resolving function/variable names in the local scope compared to going up the prototype chain. in his case its about 8 times faster in the local scope, but does in fact require a local copy of the variable.

I initially had to learn and understand JS variable resolution when i was writing a server to process Google Analytics data from our customers accounts to get some valuable business insides from the data.

The beauty of a self terminating function is that it creates a scope that is not even related to the global scope, if the variable name is not found in that scope it does not start going up scopes, and the scope itself is very clean and not polluted (unless you pollute it yourself) so its faster to resolve your variable names, vs an object with a long prototype chain. keep in mind that in the article above the prototype chain would get slower and slower the more methods and variables you added.

Just using a self invoking function as a wrapper for my array addition sped up my code 7 times. along with a bunch of other variable lookup optimizations i was able to process a GB of data per second on my T2 micro aws server with 1 GB of memory.

In the modern day era of computing i am also very confident making trade-offs for using more memory via copying that function to be closer in memory when i need it.

Also keep in mind that when it comes to low level cache hardware (like your CPU cache) its going to take advantage of the function actually being close in memory to the object, as well as probably being accessed when the variable is accessed ( taking advantages of temporal and spacial locality) when the object you are trying to use gets loaded into memory; it's likely to also load the function into the cache with it, and then you don't have to wait on all the cache misses as it traverses up the prototype tree.

OFCOURSE there will be some case somewhere where that object function for some reason takes up a huge amount of memory and its more efficient to store it in the prototype, but that will be highly unlikely.

But this kind of design pattern:

var collection = (function() { // private members var objects = [];

    // public members
    return {
        addObject: function(object) {
            objects.push(object);
        },
        removeObject: function(object) {
            var index = objects.indexOf(object);
            if (index >= 0) {
                objects.splice(index, 1);
            }
        },
        getObjects: function() {
            return JSON.parse(JSON.stringify(objects));
        }
    };
})();

Is called a module pattern and is used A LOT... like really A LOT in javascript, most of npm packages are wrapped like this for example, because it gives them a blank scope and they don't have to worry for what lives outside that function.

https://medium.com/@tkssharma/javascript-module-pattern-b4b5... -- just read through this

This is a tried and tested pattern. I didn't make this up myself lol

That's why i initially suggested that the developer is probably younger and less experienced, if you work with JS for the last 5 years you are almost guaranteed to run into this.

Re: Public and private class fields

#96
post #5

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.

I 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 t…

All 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.

Re: Public and private class fields

#97
post #42

First, like the other commenters, I'm not in love with the perlish # syntax. I'm not sure why it was wise/necessary to add a previously illegal character as a prefix, rather than adding a "private" keyword, but I'm sure there's some reason. Second, the example affords an opportunity to rant about a pet peeve of mine. "Now ask yourself, how would you implement this class in JavaScript?" I wouldn't. Listen folks: unles…

Getters/setters are useful. E.g. maybe you had a class 'Box' with a field 'area'. Later you added fields 'width' and 'height'. What are you going to do? Change 'area' to 'getArea()' and break the API? Write extra code to ensure that you update area every time you change width or height? Or write a getter that returns width*height? I'd say getter is the cleanest option in many cases.

This applies for languages which can do static type checks.

In JavaScript, there's no assurance that the object you've got even means 'area' to be a number. It could be a string indicating which warehouse the Box is in.

So yes, you bloody well bump the major version number and the consumer needs to check the errata. Pretending to maintain compatibility when you're actually messing with the meaning of things is not something which should be done silently. What happens when someone calls the 'area' setter? Does it trust the width or the height...?

Re: Public and private class fields

#98
A huge (from my perspective, at least) unsolved problem with the private members proposal is that you can't use it to build immutable objects, not realistically.

Without private members I can write something like:

  class Fruit {
    constructor(props = {}) {
      Object.assign(this, props)
      Object.freeze(this)
    }
    withSize(size) {
      return new Fruit({...this, size})
    }
  }
Now I can do:

  fruit = new Fruit({kind: 'apple'})
  // Later:
  saveFruitToDatabase(fruit.withSize(20))
This pattern works great, overall, though it isn't performant. With private members, you'd think you could declare them and also update objects using transformations. But private members don't work with Object.assign(), .entries() etc., and aren't introspectively at all. So you can't write withSize() to do partial updates without spelling out all the field names, every time.

Turns out it's quite hard to write robust, performant immutable code in JS. (Yes, I know immutable.js has Record. However, it's not compatible with getters and setters.)

Re: Public and private class fields

#99

Earlier quoted context omitted.

Making classes (or equivalent) in the way you propose - ie "make use of closures for private instance fields" - does not work well. It requires allocating a new copy of each of the class's methods every time the class is instantisted, working around the prototype system. If we're arguing about crappy misuse/abuse of JS and "doing it wrong", surely this is far worse?

what i was demonstrating by showing that design pattern is that there is already an easier and clean way to do private variables and scopes. BUT if you want to talk about its speed and efficiency here we go: It very intentionally trades memory space for faster variable resolution. plz read this article - https://www.toptal.com/javascript/javascript-prototypes-scop... he has some test code at the end that compares the…

Also to clarify something, it technically wouldn't be a closure since -

A closure is an inner scope that has a references to its outer scope.

It happens any time a function is created (technically, even global). That actually even goes for “IIF(Instantly Invoked Functions)”, since the function is created first (has references to its outer scope) and THEN is called (two separate “events” in js). The call is not part of the function decl/expr and therefore comes next. Between the two there’s a gap and that’s where you’d say there’s a closure. After that call the reference to the function ceases to exist and the garbage collection tears down the function and with that the closure too.

Re: Public and private class fields

#100

Earlier quoted context omitted.

https://en.m.wikipedia.org/wiki/WHATWG Good or bad, that is the governing body the browser makers honor.

Fair point; I get mixed up, since both organizations are pretty active and proposals are often submitted to both. Regardless, even in this case this proposal is being submitted to TC39[0]. It's in stage 3 of 4[1]. Stage 3 proposals should not be shipped on by default. There still may be spec changes between a stage 3 and stage 4 proposal. [0]: https://github.com/tc39/proposal-class-fields [1]: https://tc39.github.io/…

Gotcha. Didn’t know about TC39 for the ES language concern distinct from web / browser stuff.
Post reply on HN