Closed hodonsky closed 4 years ago
However as this method ends up as part of the class, it should have access to
this.#
properties.
That is not how private fields in JS work - if you could access them by adding a method to the class, they wouldn't really be private. Methods which need access to private fields need to be defined as part of the class.
Uhhh, that sounds more like a 'protected' variable. If the method is in the instance it should have access to it's private methods and properties...
What you're suggesting is re-implementing the entire class, seems a little ridiculous.
@hodonsky the semantic you expect is what "protected" might be in a classical inheritance language; in those languages, "private" things are not available to subclasses.
The code inside Base
can (and does) install and access private fields on instances of a proper subclass (that's defined with class
and extends
, and calls super()
), but the code inside the subclass can not.
It's not a subclass... it's extended by itself on instantiation.
If I had a subclass or an actual extended class, I could pass certain expectations around during instantiation. I'm trying to alleviate the need for that in this particular instance. However, I don't want the consumer to be able to console.log(new Base().config)
, but I do want access to it in the extended functions
Oh, it just hit me why that doesn't work in JS.... getters and setters for values aren't blocked by scope here. Dang...
Thoughts on how I might achieve what I want within lexical scope and JS restrictions?
If you really want a given member to be private, but do want some other trusted code to have access to it, the point of access still needs to be defined within the class body (because that’s the scope of private names). However you could “pull them off” so that they’re only available to the code that runs before they’ve been removed, e.g.:
class Foo {
#bar;
static getBar(foo) {
return foo.#bar;
}
static setBar(foo, bar) {
foo.#bar = bar;
}
}
const { getBar, setBar } = Foo;
delete Foo.getBar;
delete Foo.setBar;
// code here can use getBar/setBar to indirectly interact with the private #bar member of foo instances
Essentially this is elevating the scope of access to module scope rather than class body scope, though it’s awkward. Note that if you crossed module boundaries — like, actually exported getBar
/setBar
— privacy would be lost entirely, since anything can import any module (but if you’re doing code transforms like bundling, this may be moot).
Yeah... I figured that was my only option. Thanks for your replies
@hodonsky for your particular case, I'd do something like
// file1.js
export class Base {
#config = {}
constructor(config, dep){
this.#config = { ...config }
this.#extend( dep)
}
#extend(dep) {
const { name, fn } = dep
this[name] = fn(() => this.#config, v => { this.#config = v; });
}
}
// file2.js
const funfunFN = (getConfig, setConfig) => function() {
console.log( getConfig() )
};
new Base({},{ name: 'funfunFN', fn: funfunFN })
I'm having this error ONLY when the variable is private. However as this method ends up as part of the class, it should have access to
this.#
properties.Case:
Any thoughts?