tc39 / proposal-private-methods

Private methods and getter/setters for ES6 classes
https://arai-a.github.io/ecma262-compare/?pr=1668
345 stars 37 forks source link

Stop this proposal #10

Closed uyeong closed 5 years ago

uyeong commented 7 years ago

I think it will impair existing elegance of Javascript so it should be omitted.

acidsound commented 7 years ago

I agree. the OO is useless. and getters/setters too.

rico345100 commented 7 years ago

I totally agree with him. In the traditional class based approach, this might be needed, so as TypeScript does. But JavaScript is not class based, it's based on prototype linked object oriented language.

"Class" in Javascript is a way different from others, and mixing original class based features into JavaScript is really bad idea. IMO, generally I don't use "private field" in JavaScript, because it doesn't needed at all.

Some of the people can say: "What if you need a encapsulation in JavaScript?" My answer is: "You can do encapsulate your data in JavaScript without private fields."

I know, using closure to implement encapsulation and using private field is quite different, not just syntactic looks, but I just want to ask one question: "Does it really need encapsulation in JavaScript?"

If you really needed that one, I just recommend to use TypeScript. This proposal makes hard to read other people to didn't know what # means. Making readable code is also most important part of modern days, there is no programming language that uses "#" as private field in class.

If this proposal passed, later we couldn't understand what code looks like. Who knows? What kind of strange syntax will added future?

littledan commented 7 years ago

It's true, this proposal rests on people being able to learn what # means.

Aside from the difficult of learning that # means private, and the proposition that classes are bad, do you see further disadvantages to the proposal?

futagoza commented 7 years ago

@littledan personally, for me it's quite easy to learn, but I simply don't like the look of the code with #, it just looks ugly, no offence m8 😄

trotyl commented 7 years ago

@futagoza But private fields already got stage 3, there will be # anyway, what's the meaning of just objecting # in methods?

futagoza commented 7 years ago

@trotyl I'm not objecting, I'm giving my opinion on the syntax look. For private values it looks fine, but once you start using it for methods as well the syntax starts to look weird to me, but if it goes through anyway because others want it, I don't mind.

stevenvachon commented 7 years ago

This spec causes confusion with Class#method, such as Array#includes.

claudepache commented 7 years ago

I simply don't like the look of the code with #, it just looks ugly

On the contrary, I find the # token of class fields very elegant; let’s accelerate this proposal!

claudepache commented 7 years ago

Once you have private fields, private methods and accessors are a natural extension; and if you haven’t them, people will try to emulate them using private fields. Reusing the example of the explainer:

class Counter extends HTMLElement {
    // real private field
    #xValue = 0;

    // emulated private accessors (not really accessors, because of syntax constraints)
    #getX = function () { return #xValue; };
    #setX = function (value) {
        this.#xValue = value; 
        window.requestAnimationFrame(this.#render.bind(this));
    };

    // emulated private method
    #clicked = function () {
        this.#setX(this.#getX() + 1);
    };

    // etc.
}

So,... it’s too late to stop the private stuff now; it had to be done with private fields.

stevenvachon commented 7 years ago

This is a sign that JavaScript is nearing its end. Something will overtake it, like Dart tried to do.

tasogare3710 commented 7 years ago

I agree. Field privacy is not based on class. It is based on abstract data type and encapsulation.

Because the design philosophy is different, these two are not necessary for javascript.

littledan commented 7 years ago

@tasogare3710 Do you think JS has enough facilities for encapsulation already?

littledan commented 7 years ago

@stevenvachon I never understood this idea that languages reach their end once they get features. Do you have an idea of a language that went through that kind of pattern? (C++ seems to be doing very well within its domain, for one; I think its biggest problems (undefined behavior and lack of memory safety) are not about too many features).

stevenvachon commented 7 years ago

@littledan it's not the features themselves, but the cryptic syntaxes that JavaScript is often limited to.

littledan commented 7 years ago

@stevenvachon If we used @ rather than #, how bad would it be?

tasogare3710 commented 7 years ago

@littledan If soft private is not enough, I think that other languages should be used.

In addition, # is generally a symbol representing the interned string in the language where the symbol is first class citizen.

Nobody thinks that it is a private field. I do not want to hard code reading.

stevenvachon commented 7 years ago

As I understood it, # was chosen because it is not currently accepted as valid syntax, where @ is.

littledan commented 7 years ago

@ isn't currently valid syntax, but it's proposed for decorators. We discussed whether decorators and private state should "swap sigils", but ended up deciding that it should stay with decorators as @ and private as #. The hope is that people will get used to # over time. It seems like a large part of the negativity about private fields and methods is that we are using # rather than @.

tasogare3710 commented 7 years ago

@littledan Why do we need to introduce privacy newly into the property?

Since javascript uses properties from the beginning(consistently from original javascript to currently), internally always have slots. So, I think in than enough just to be able to freely define additional slot without introducing a new privacy.

This will have the same effect as newly introducing privacy.

shalldie commented 6 years ago

Yes , it should be stopped!

The # is the same as !@$%^&*() why not use $,or user can custom it.

class Person{
    $x=0;

    $getX(){
    }
}
tasogare3710 commented 6 years ago

The issue with Sigil is only a small misfortune.

I think that people who oppose this proposal are mainly the same thought as @rico345100. At least I do not want Clyde and Fred to be killed by ecmascript.

vjpr commented 6 years ago

The # looks ridiculously bad and adds so much visual noise. It will make Javascript such an ugly-looking language. At the moment there are minimal symbols in the typical file of code, and they are visually lightweight. E.g. (){.[:<>. Compare that to #%$&* which are super busy, and confronting. You can see it just by looking.

The @ is better, but I think its such a drastic way to make the change by doing a lot of stuff all at once:

  1. introducing new behavior of hiding internals
  2. introducing new syntax, and not minor new syntax, but syntax that will dramatically change the look of all Javascript code
  3. doing it in a completely new way not seen in a modern language before by identifying private methods at the location of their usage i.e. this.#foo (sigil)

Why not start with adding the new behavior and enabling it through a comment annotation using a babel plugin like so:

// @private
foo() {}

Then people can try it out, see if they use it, if they like it, etc. FlowType could adopt it and type check using it. And this comment syntax might even be fine for a long time.

Then if its a great feature, start the discussion about the declaration syntax first. Maybe introduce private foo().

Then we could turn the private into a @, and talk about adding this.@foo.

michelre commented 6 years ago

This should not be part of JavaScript. If people want to use this kind of thing, they should use typescript

tasogare3710 commented 6 years ago

The first thing to mention is that @littledan said "...and the proposition that classes are bad", but the class is not bad.

I agree that the # looks ridiculously bad. However, please remember everyone. Since javascript(or ecmascript) uses delegation rather than inheritance, we assert useful mechanism in class based is not necessarily not useful in prototype based.

And, i understand one thing.

People who dislike # seem to have many people in favor of this proposal unless javascript use #.

However, this issue is an issue against the private field itself for the reason "javascript does not need a private field".

I have a suggestion. How about separating Sigil issue from this issue?

bakkot commented 6 years ago

@tasogare3710, we've heard from a lot of people, especially library authors and frameworks like node, that they do need private fields.

Closures don't provide the same sort of encapsulation - they don't provide a good way for many objects to be able to examine each other's state without exposing that state to the world.

For example, it's very difficult to use closures to implement something like

class Point {
  #x;
  #y;
  equals(p) {
    return this.#x === p.#x && this.#y === p.#y;
  }
  // other methods
}

So, while I understand that you have not had a need for private fields, that's not enough to establish that the language doesn't need them, especially when we've heard from a lot of people that they really do.

vjpr commented 6 years ago

we've heard from a lot of people, especially library authors and frameworks like node, that they do need private fields.

What makes JS nice is that it is hackable and monkey-patchable. You can poke around. There are so many internal node things that I've used and monkey-patched over the years that are absolutely necessary. And sometimes its good to be able to look around just for debugging purposes. E.g. inspecting the internal state of a library you are using.

I think if you are a library author, perhaps you have different priorities than a consumer. If there is a bug, you already have the project checked-out, and you can fix your own library, or you know potential workarounds. If you are consuming a library, you just want things to work, monkey-patch if necessary, and move on. Making everything private assumes that there are never bugs that can only be debugged by inspecting the internals, but every library has bugs. And since there are so many toolchains involved these days, its not so easy to just git clone, npm link, and inspect, and usually npm dists are not bundled with sources.

bakkot commented 6 years ago

@vjpr, that's never been entirely true - you can't poke around inside of closed-over variables (except with debugging tools, of course, but debugging tools will be just as free to modify private fields as they are to modify closed-over variables). Indeed, the sort of privacy provided by closures has very much served as a model for private fields.

That aside, this is the reflection vs encapsulation debate. It's one the committee is very aware of, but having considered it at length we came down on the side of encapsulation. There are of course major benefits to allowing reflection, which we all are familiar with, but there are also real costs. (And I think that's something other languages have been finding as well.)

vjpr commented 6 years ago

@bakkot

class Runner {
  #items
  run() { this.#items.map(x => this.#foo(x)) }
  #foo() { console.log(x.foo) }
}
const runner = new Runner
console.log(runner.#items)

Every dev would make items private. Now if the dev wants to inspect items during development, they need to add a getter. Then if they think the user should have access in prod they must decide whether to add a getter. It starts to make JS feel like Java.

There are two cases:

I've read the faq, and a bunch of the discussion issues here. I think library developers requests are being prioritized over users, and there are more users than library developers, and as I mentioned above they have different priorities.

Anyway, if it has to happen, then please use the @ instead. BTW, what is the likelihood of things changing at this point?

tasogare3710 commented 6 years ago

@bakkot My opinion is consistent.

If you have problems with the following code, you should use other languages instead of javascript.

var private_fields = new WeakMap
class Point {
  constructor(x, y) {
    private_fields.set(this, {x, y})
  }

  equals(p) {
    var {x: my_x, y: my_y} = private_fields.get(this)
    var {x, y} = private_fields.get(p)
    return my_x === x && my_y === y
  }
}

var __x__ = Symbol("x")
var __y__ = Symbol("y")

class Point2 {
  constructor(x, y) {
    this[__x__] = x
    this[__y__] = y
  }

  equals(p) {
    return this[__x__] === p[__x__] && this[__y__] === p[__y__]
  }
}

So, while I understand that you have not had a need for private fields, that's not enough to establish that the language doesn't need them, especially when we've heard from a lot of people that they really do.

Delegation does not require other different objects in advance to make a new object.

However, private fields currently have classes only. This leads to the wrong design in javascript which is a prototype based OOP.

The wrong design is to give the illusion that javascript must prepare another different objects before creating a new object. It is a characteristic of inheritance, not delegation.

In javascript(and prototype based OOP), constructor functions and class constructors(these are instance creations) must be used to remove boilerplate code for initialization.

There is "one-of-a-kind objects" created by other methods in javascript.

function SameKindObject() {
    // A lots of initializations.
    // However, it has common properties.
}

var common1 = new SameKindObject
var common2 = new SameKindObject
var common3 = new SameKindObject

// this is "one-of-a-kind"
var not_common = {
    // include unique properties
}

Even though allow private fields, you can not have private unique properties in "one-of-a-kind objects" in the current proposal. This part has room for discussion.

Btw, is inspection included in reflection? Javascript is an easy to inspect by nature(for-in and json etc).

Although we should not test private fields, inspection is essential for logging, debugging and externalization etc.

However, private fields may make to these difficulties.

bakkot commented 6 years ago

@vjpr

Now if the dev wants to inspect items during development, they need to add a getter.

Or use development tools, or for that matter just make it public.

Then if they think the user should have access in prod they must decide whether to add a getter.

Again, or just make it public. I don't understand why you'd make something private which you wanted users to have access to.

I want to prevent the user accessing internals. No developer would ever ask for this. If they did, they would be saying "its hard to tell what is private and what is not".

Many, many developers have asked for this. This is precisely the hard-private vs soft-private debate.

They're not saying "it's hard to tell what is private". They're saying "if this is not actually private, it's part of my public API, and my users will read and change it regardless of how much I intended them not to, and that makes my life much more difficult".

I think library developers requests are being prioritized over users, and there are more users than library developers, and as I mentioned above they have different priorities.

It is part of our mandate to balance different needs, yes.

But most users don't need to access internal state of libraries, I think; it's only a fairly small subset who want this. And to a large extent the needs of library authors are the needs of users, because users need those library authors to keep maintaining their libraries.

Anyway, if it has to happen, then please use the @ instead.

We discussed it at some length a while ago and decided to go with the current setup. We might revisit if there's some reason to, but it would have to be something more than "I don't like it".

BTW, what is the likelihood of things changing at this point?

If something comes up which we hadn't thought about, reasonably high. It's very unlikely that we will change anything purely on the basis of things we've already discussed at length, though, like hard vs soft private.

@tasogare3710

If you have problems with the following code, you should use other languages instead of javascript

This is not the opinion of the committee. WeakMaps work for this, but are non-obvious, somewhat awkward to use, and error-prone.

Even though allow private fields, you can not have private unique properties in "one-of-a-kind objects" in the current proposal. This part has room for discussion.

Yes, this is something we've thought about. We may well add them later, just not as a part of this proposal. However, this use case is already reasonably well met by closures, I think:

var priv = 1;
var obj = {
  pub: 2;
  method() {
    return this.pub + priv;
  }
};

Btw, is inspection included in reflection?

Yes.

Javascript is an easy to inspect by nature

Not always. There has never been a way, as part of the language, to inspect the variables a function closes over.

Although we should not test private fields, inspection is essential for logging, debugging and externalization etc.

Again, this is the reflection vs encapsulation debate, which we've talked about a great deal. These are points which have been brought up (many times) before, and even taking them into account, we still felt that having a reasonably easy way to provide encapsulation was important.

That said, logging and debugging can be accomplished by development tools, which can access whatever they want, including private fields. And I'm not sure what you mean by externalization; there are a couple of ways I normally encounter that term, but none of them seem like they'd really be impeded by private fields.

In any case, if the developer doesn't actually want encapsulation, they shouldn't use private fields. There is a fundamental conflict between reflection and encapsulation; if the benefits of reflection (including inspection) to a specific developer outweigh the benefits of encapsulation, then just don't use private fields. That's not a sufficiently good reason to deny them to everyone.

vjpr commented 6 years ago

@bakkot

Or use development tools, or for that matter just make it public.

Its not easy to make something public anymore. You have to change the variable name everywhere its used because of the sigil. It severely handicaps the developer. Testing too becomes more difficult.

I don't understand why you'd make something private which you wanted users to have access to.

Because you don't want users to rely on it. But what if its required to track down a bug? To check on the internal state? From personal experience, I feel like I'm always inspecting private state all the time tracking down bugs. JS world moves fast and things break often.

I would argue that library devs and consumers both want to know if something is private or no, but don't want their hands tied.

Many, many developers have asked for this.

I am talking about library consumers/developers in this para.

If someone is using private apis, they will not expect their code to seamlessly upgrade. But right now, you can't easily tell what is private or not. If we know what is private, we can use tooling to print warnings to developers that they are using private stuff.


I understand that a lot of thought has been put into this proposal, and that everything naturally flows towards this solution if you follow through the constraints that arise in the FAQ from the alternatives, but I still feel like its a worrying direction that JS is taking.

bakkot commented 6 years ago

@vjpr

Its not easy to make something public anymore. You have to change the variable name everywhere its used because of the sigil.

This is something I'd expect one's editor to take care of. Although even with just a raw text editor, you can probably find-replace #foo with _foo and have everything continue to work, unless you happen to already have a field named _foo on the same class.

Because you don't want users to rely on it.

It turns out that users will, as a question of fact, rely on anything the language gives them access to. If you don't want users to rely on it, it must be actually private.

To check on the internal state? From personal experience, I feel like I'm always inspecting private state all the time tracking down bugs.

Dev tools will be able to give access to private fields just as they are already able to give access to closed-over variables; there's no problem there.

If someone is using private apis, they will not expect their code to seamlessly upgrade.

As it turns out, yes, they will. Maybe they shouldn't, but they will.

Nor is the burden always borne by the people using the private APIs: Suppose library A has some internal API exposed in version 1.0.0, and library B uses that API. Consumer C depends upon both A and B. Then A updates to version 1.0.1, incidentally removing the internal API upon which B depended (figuring that it was intended to be private, so it's OK to remove in a patch release). Then the next time consumer C tries to install their package, they find it broken and have no idea why.

Consumer C reasonably expected their code to seamlessly upgrade - 1.0.1 is just a patch release from 1.0.0, after all. But it didn't, and now odds are they're going to go complain to A that their patch release had a breaking change (quite possibly without even mention the use of B, not seeing why it would be relevant).

But right now, you can't easily tell what is private or not.

There's a fairly wide convention that _-prefixed names are intended as internal; you can also use a Symbol as a property name to make it require reflection to get at. The problem is that these aren't private. You can't tell what is private or not because nothing is, except closed-over variables; you can only tell what the developer would like to suggest is private, for which _-prefixed names serve just fine, I think.

I still feel like its a worrying direction that JS is taking.

I don't really understand why this feels like a deviation from JS. The sort of privacy provided by private fields is very similar to the sort of privacy provided by closures.

vjpr commented 6 years ago

This is something I'd expect one's editor to take care of.

Yes, an in-place refactor in WebStorm would work. But still very cumbersome. I don't want to rely on an IDE. After this proposal, it would be easier to make something private/public in Java/C++ than JS. What if we end up adding friend classes...

Dev tools will be able to give access to private fields

No-one uses dev tools/--inspector for typical Node development. Its all console.log.

Nor is the burden always borne by the people using the private APIs...

Good point.

What about adding a flag to allow seeing privates in dire cases? I think someone already mentioned this.

There's a fairly wide convention...

I know, but I don't use it and a lot of people don't. I've wanted syntax to know something is private for a long time, but I always thought we would just get the private keyword - never expected the sigil and the #. I would back a private keyword 100%. But the Java-style encapsulation requirements of this proposal make it unfeasible as I have read, but also cause such dramatic change to the language syntax.

I don't really understand why this feels like a deviation from JS.

No doubt at least soft-private is needed, I think everyone would agree. The addition of a simple private keyword would have taken us so far though, and would still feel and look like JS.

tasogare3710 commented 6 years ago

@bakkot

Not always. There has never been a way, as part of the language, to inspect the variables a function closes over.

Look at the snippet related to this.

In the following snippet there is a call JSON.stringify (p0, Point.prototype.toJSON.bind (p0)).

This is an error if you do not bind p0 toPoint.prototype.toJSON, but in this way javascript is often given this value explicitly. Please pay attention to this.

function assert(cond) {
  if(!cond) {
    throw new Error("assertion error: a not b")
  }
}

var private_fields = new WeakMap
class Point {
  constructor(x, y) {
    private_fields.set(this, {x, y})
  }

  static fromJSON(text) {
    var {x, y} = JSON.parse(text)
    return new Point(x, y)
  }

  static internalize(name, val) {
    return Point.fromJSON(val)
  }

  equals(p) {
    var {x: my_x, y: my_y} = private_fields.get(this)
    var {x, y} = private_fields.get(p)
    return my_x === x && my_y === y
  }

  toJSON(key) {
    return JSON.stringify(private_fields.get(this))
  }

  serialize(key, value) {
    return value
  }
}

const p0 = new Point(1,2)
assert(p0.equals(new Point(1,2)))

const jsonText = JSON.stringify(p0, Point.prototype.toJSON.bind(p0))
assert(jsonText === JSON.stringify(p0))

const p1 = JSON.parse(jsonText, Point.internalize)
assert(p0.equals(p1))
assert(JSON.stringify(p0, p0.serialize) === JSON.stringify(p0))

As in this example, when given the this value from the outside, how is it to work correct in a private field?

This problem does not occur because internalize/internalize functions uses only given arguments.

With WeakMap we can easily expose closed over value, but this is reasonable behavior as javascript.

However, when a private field is added, which one happy to recognize which behavior is correct?

Since it is a private field it is better not to be exposed? Or is it better to be able to expose closed over value because of its inherent flexibility and dynamic nature in javascript?

Same can be said about destructuring assignment.

Since this proposal includes such a dilemma, i think that do not decide only the part of class about the private field, but also explain the other parts and necessary to discuss it.

If the current incomplete proposal is added to the specification as it is, there is a risk of leading to the wrong design as already mentioned, a part other than the class about the private field if add later the specification of, it's too late.

In a method to correct defects later it is difficult to correct the wrong design that has already been done.

So, I think that we must stop this proposal first.

tasogare3710 commented 6 years ago

@bakkot

I don't really understand why this feels like a deviation from JS.

oh sorry, this was not addressed to me, so I read it for the first time, but I already have one concrete example on this subject.

Is that because you said it as follows?

that's not enough to establish that the language doesn't need them

In response to your reply, I said like this:

This leads to the wrong design in javascript which is a prototype based OOP.

What do you think about this?

You are only saying Yes, this is something we 've thought about. About "one-of-a-kind objects".

And many people say about private fields at this issue this is a ugly thing not part of javascript.

stevenvachon commented 6 years ago

However, private fields currently have classes only. This leads to the wrong design in javascript which is a prototype based OOP.

I agree with this, because classes were added to make JavaScript easier, not to replace prototypes. This functionality should exist on plain objects (including prototypes) before being designed for classes. However, doing so:

const obj = { #propA: 0 };
obj.#propB = 1;
obj.func = function() {
  // this likely isn't even possible since `this === obj`
  return [this.#propA, this.#propB].join();
};

console.log('propA' in obj, '#propA' in obj, obj.#propA) //-> false, false, undefined
console.log('propB' in obj, '#propB' in obj, obj.#propB) //-> false, false, undefined
console.log(obj.func()) //-> '0,1'

…causes confusion with regular string properties containing "#":

const obj = { '#propA': 0 };
obj['#propB'] = 1;

console.log('propA' in obj, '#propA' in obj) //-> false, true
console.log('propB' in obj, '#propB' in obj) //-> false, true

Perhaps "private" should simply mean non-enumerable so that they're just property descriptors, alternatively created/modified via Object.defineProperty.

In the end, do we really need this feature at all? Within a module, a variable or function outside the class can simply not be exported.

tasogare3710 commented 6 years ago

@stevenvachon

…causes confusion with regular string properties containing "#":

How about looks like ComputedPropertyName?

const obj = { [#propA]: 0 };

In any case, I think that it is room for discussion to remain in the future.

Perhaps "private" should simply mean non-enumerable so that they're just property descriptors, alternatively created/modified via Object.defineProperty.

That's true. Private Name specification type may not be necessary.

In the end, do we really need this feature at all? Within a module, a variable or function outside the class can simply not be exported.

I agree. Unless the developer inadvertently exposes it.

RangerMauve commented 6 years ago

I think this is also wanted by people implementing JS environments because they want to implement more of the core types in pure JS, which isn't possible for them to do safely since JS doesn't have private vars yet.

The JS spec uses private fields in a lot of places and using them requires either writing it in native code, or adding weird engine features.

Details:

tasogare3710 commented 6 years ago

In any case, I think that it is room for discussion to remain in the future.

I'd like to supplement this, I think it is necessary to have a place to discuss comprehensively without dividing field and method for Privacy.

Also about class and object initializer and destructuring assignment too.

amatiasq commented 6 years ago

@RangerMauve JS supports encapsulation by closure since it was invented and with WeakMaps since 2015.

RangerMauve commented 6 years ago

@amatiasq Of course closures work for hiding variables, but they're not very good for building classes that need to have a high level of performance. Instead of using the prototype chain for methods, any methods that use the private variables would need to be redefined in the constructor (or whatever closure generating your object) every time an object is initialized. Most libraries that focus on high-performance code make use of the prototype chain to improve efficiency and avoid object literals and closures.

Any pattern that relies on access to a weakmap will have similar limitations.

For 80% of the code out there won't be hot code that needs this extra bit of performance, but for the code that does, it's very important to get high performance and high safety.

tasogare3710 commented 6 years ago

@RangerMauve Modern js VM itself is fast enough, slow is part of the web. It has various external factors and its concern is off the mark. Even if replacing the WeakMap whole web will remain slow.

RangerMauve commented 6 years ago

@tasogare3710 Do you think you could point me to documentation from a high-performance library saying that using closures is okay?

Sure the whole web is slow, but the slow parts of the web aren't necessarily going to be the hot paths in your code, optimizing for high performance is important in libraries that get used a lot in your application logic. As well, I mentioned that private properties could pave the way for implementing more of the JS runtime in JS itself (see links in my comment), which you would want to write in the most efficient way possible.

tasogare3710 commented 6 years ago

@RangerMauve Your concern is about the high-performance, is not it?

There is no big difference in performance between tracing the scope-chain using closures and tracing the scope-chain using the var(or let) variable. If there it is due to the difference of the optimization degree of each implementations. However, when implementing private property, there are concerns about performance mainly when WeakMap is used.

Also, for the following code of https: //v8project.blogspot.jp/2016/02/v8-extras.html,

(function(global, binding, v8) {
  'use strict';
  const Object = global.Object;
  const x = v8.createPrivateSymbol('x');
  const y = v8.createPrivateSymbol('y');

  class Vec2 {
    constructor(theX, theY) {
      this[x] = theX;
      this[y] = theY;
    }

    norm() {
      return binding.computeNorm(this[x], this[y]);
    }
  }

  Object.defineProperty(global, 'Vec2', {
    value: Vec2,
    enumerable: false,
    configurable: true,
    writable: true
  });

  binding.Vec2 = Vec2;
});

The only special code that can be removed if private is added isv8.createPrivateSymbol. Other special codes still remain necessary. In addition, this code can not remove the closure because it uses a closure to not contaminate the namespace.

RangerMauve commented 6 years ago

@tasogare3710 I don't see why the optimizations that engines use for the prototype chain (hidden classes in Chrome) wouldn't also apply to private properties. The difference in optimization levels is the most important difference to consider when writing code to run fast in JS engines, hypothetical differences between the complexity of doing different things according to the spec doesn't matter as much as actual numbers when executing your code.

Regarding your example:

littledan commented 6 years ago

My understanding from discussions with V8 engineers is that private fields should be more optimizable than WeakMaps and closures, both due to various GC-related costs and because they fit in more or less to the inline cache system. It's possible I've misunderstood, however. If you have any information about why this might not be true in some JS implementations, it'd be good to hear why not.

cztomsik commented 6 years ago

It is really common to call private methods and check private fields during unit-tests. There is always limited time for "hygiene" tasks and it has to be simple to write unit-test.

slahser1992 commented 6 years ago

why not use 'local' to define private props or function like chrome tell us?

glen-84 commented 6 years ago

A summary of feedback regarding the # sigil prefix

lewisdiamond commented 6 years ago

Let me call a "private" method if I want to. I'd rather the current status of naming the method with a leading underscore to "warn" me that I'm not using the official API than a JS engine that throws on me when I knowingly call a private method.

"Users of the custom element don't have the power to mess around with any of its internals." who's idea is it to limit the user? How about empowering the user instead? I have the source, I can understand the code, I can mess around with it if I want to.