javascript - How to access a private field in a class - Stack Overflow
class - Private properties in JavaScript ES6 classes - Stack Overflow
Access private variables from different instance of object but same class
Why are inherited private class fields not accessible on the subclass, after instantiation? +are there any workarounds?
Videos
None of your fields are private. Just prefix movieName with underscore.
showMovieName() {
return `${this._movieName}`;
}
In your code you need to change return `${movieName}`; to return `${this._movieName}`;
More info
Your example uses the public field declaration syntax of classes to declare two public instance properties named _movieName and _category.
Using underscores as property name prefixes is an old-fashioned (although still common) way to indicate that a property is intended to be private (although this approach offers no enforcement whatsoever).
JavaScript now has private class fields. These can be declared using the # prefix ("hash name syntax") and cannot be accessed in any way by anything outside of the class body itself.
Private fields are added before the constructor runs and are not inherited.
class Movie {
#movieName;
constructor(movieName) {
this.#movieName = movieName;
}
showMovieName() {
return `${this.#movieName}`;
}
}
const movie1 = new Movie('Avengers');
console.log(movie1.showMovieName());
Private class features is now supported by the majority of browsers.
class Something {
#property;
constructor(){
this.#property = "test";
}
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return this.#property;
}
}
const instance = new Something();
console.log(instance.property); //=> undefined
console.log(instance.privateMethod); //=> undefined
console.log(instance.getPrivateMessage()); //=> test
console.log(instance.#property); //=> Syntax error
Update: See others answer, this is outdated.
Short answer, no, there is no native support for private properties with ES6 classes.
But you could mimic that behaviour by not attaching the new properties to the object, but keeping them inside a class constructor, and use getters and setters to reach the hidden properties. Note that the getters and setters gets redefine on each new instance of the class.
ES6
class Person {
constructor(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
}
ES5
function Person(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
Solved!
Any tips on how to access private variables of a different instance of object but same class without using setter or getters as well?
Thanks
Edit: A sample code with what I am trying to achieve https://pastebin.com/P1GXhwQv
tldr: i found a method to pass values to private properties declared "further up the chain".. in a subclass definition. i was pleased with this, very pleased, but then i realized that afterwards, even while using getters/setters the private properties are inaccessible on the object, despite the JavaScript debug console showing them on them.
i know there is high strangeness around private properties. But it would mean the world to me, if i could just access them.. somehow.
No, there's no way to do it. That would essentially be scoping in reverse.
Methods defined inside the constructor have access to private variables because all functions have access to the scope in which they were defined.
Methods defined on a prototype are not defined within the scope of the constructor, and will not have access to the constructor's local variables.
You can still have private variables, but if you want methods defined on the prototype to have access to them, you should define getters and setters on the this object, which the prototype methods (along with everything else) will have access to. For example:
function Person(name, secret) {
// public
this.name = name;
// private
var secret = secret;
// public methods have access to private members
this.setSecret = function(s) {
secret = s;
}
this.getSecret = function() {
return secret;
}
}
// Must use getters/setters
Person.prototype.spillSecret = function() { alert(this.getSecret()); };
Update: With ES6, there is a better way:
Long story short, you can use the new Symbol to create private fields.
Here's a great description: https://curiosity-driven.org/private-properties-in-javascript
Example:
var Person = (function() {
// Only Person can access nameSymbol
var nameSymbol = Symbol('name');
function Person(name) {
this[nameSymbol] = name;
}
Person.prototype.getName = function() {
return this[nameSymbol];
};
return Person;
}());
For all modern browsers with ES5:
You can use just Closures
The simplest way to construct objects is to avoid prototypal inheritance altogether. Just define the private variables and public functions within the closure, and all public methods will have private access to the variables.
Or you can use just Prototypes
In JavaScript, prototypal inheritance is primarily an optimization. It allows multiple instances to share prototype methods, rather than each instance having its own methods.
The drawback is that this is the only thing that's different each time a prototypal function is called.
Therefore, any private fields must be accessible through this, which means they're going to be public. So we just stick to naming conventions for _private fields.
Don't bother mixing Closures with Prototypes
I think you shouldn't mix closure variables with prototype methods. You should use one or the other.
When you use a closure to access a private variable, prototype methods cannot access the variable. So, you have to expose the closure onto this, which means that you're exposing it publicly one way or another. There's very little to gain with this approach.
Which do I choose?
For really simple objects, just use a plain object with closures.
If you need prototypal inheritance -- for inheritance, performance, etc. -- then stick with the "_private" naming convention, and don't bother with closures.
I don't understand why JS developers try SO hard to make fields truly private.