tc39 / proposal-class-fields

Orthogonally-informed combination of public and private fields proposals
https://arai-a.github.io/ecma262-compare/?pr=1668
1.72k stars 113 forks source link

I think #private fields can reduce flexibility of JavaScript #284

Closed mikeconley12 closed 4 years ago

mikeconley12 commented 4 years ago

Hi!

I think #private fields can reduce flexibility of JavaScript. For example, how can I access #private fields from prototype methods in the following example:

// greeter.js
class Greeter {
    #name;
    constructor(name) {
        this.#name = name;
    }
    greet() {
        console.log(`hello ${this.#name}`);
    }
}

// another-module.js
Greeter.prototype.myAwesomeGreet = function() {
    // how can I access this.#name from here?
}
nicolo-ribaudo commented 4 years ago

You are right: in your example, it isn't possible to access this.#name in the myAwesomeGreet function. If it was possible, then you would be able to "steal" any private variable by simply adding a function on the prototype of the object. If this is ok for you (as the author of the class), then you can directly use a public field.

Also, this "lack of flexibility" can already be easily achieved in JavaScript, so private fields don't add any new restrictions from this point of view. From example, using the already widespread "factory function" pattern, how would you get name?

// greeter.js

export const makeGreeter = (name) => ({
  greet() {
    console.log(`hello ${name}`);
  }
});

makeGreeter("Mike").greet(); // Logs "Mike"
// another-module.js

const enhanceGreeter = (greeter) => ({
  ...greeter,
  myAwesomeGreet() {
    // how can I access name from here?
  }
});

enhanceGreeter(makeGreeter("make")).myAwesomeGreet(); // ?
ljharb commented 4 years ago

This is also how normal variable scoping works in JS - you can’t access variables outside the lexical scope they’re declared in. This is a desired property for class instances, that private fields provides.

rdking commented 4 years ago

@mikeconley12 While #private fields definitely do reduce the flexibility of Javascript when they're used, this isn't one of the ways. No matter how private might be implemented, if anything allows the class structure to be augmented with new functions and grants those new functions access to the private data, it also makes private soft and leak-able. No viable implementation of private should do this.

mikeconley12 commented 4 years ago

Thanks for the answers!

But still, is there any way to "hack" the #private properties?

I understand that the hack will be a bad practice. But I'm curious :)

nicolo-ribaudo commented 4 years ago

Nope, otherwise they wouldn't be private :stuck_out_tongue:

But you can expose a public getter/setter which handles public interactions with the field.

littledan commented 4 years ago

Closing as this question has been answered by @nicolo-ribaudo.

mikeconley12 commented 4 years ago

Nope, otherwise they wouldn't be private

But you can expose a public getter/setter which handles public interactions with the field.

@nicolo-ribaudo But this article https://2ality.com/2019/07/private-class-fields.html#private-fields-spec says that "private fields are managed via a data structure that is attached to objects". If so and this data structure is accessible from JS code, then we can modify it

ljharb commented 4 years ago

It is not accessible from JS code, or it wouldn’t be private.