JS class getter setters [duplicate] - javascript

This question already has answers here:
JSON stringify ES6 class property with getter/setter
(7 answers)
Closed 4 years ago.
According to Martin, this syntax can be used to define a class in nodeJS:
class Person {
constructor() {
this.id = 'id_1';
}
set name(name) {
this._name = name;
}
get name() {
return this._name;
}
usage:
myPerson.name = "Saul"; // save the value in `_name` variable.
Slight problem with this convention is that calling JSON.stringify(myPerson) will print the following:
{
"_name": "Saul"
}
But if I remove the underline from the setter function, and write it as the following:
set name(name) {
this.name = name;
}
the setter function will recursively call itself forever. So is there no way of using this nice getter-setter syntax, and still use the name property? I'm running nodejs.

I dont see a problem at all here. If you deserialize it, it works as expected:
const saul = Object.assign(new Person, JSON.parse('{"_name": "Saul"}'));
console.log(saul.name);

Related

"this" in JavaScript classes why it's throwing this error? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
How does the "this" keyword in Javascript act within an object literal? [duplicate]
(4 answers)
Closed 1 year ago.
when it comes to this in javascript classes it suppose to refer to the class instances but at
somechildmethod() method it don't it throws an error saying TypeError: Cannot read property 'name' of undefined and I know this error will go away if I use the arrow function but I want to know why please!
class parent {
constructor(name, score) {
this.name = name;
this.score = score;
}
someparentmethod() {
console.log("Hi!");
}
}
class child extends parent {
constructor(name, score, thirdprop) {
super(name, score);
this.thirdprop = thirdprop;
}
somechildmethod() {
return function () {
console.log(this.name);
};
}
}
const child1 = new child("zahal", 1);
const child2 = child1.somechildmethod();
child2();

Why use getter/setter in JS and not access the property directly? [duplicate]

This question already has answers here:
Why use getters and setters/accessors?
(37 answers)
Closed 3 years ago.
The following two codes are equivalent and provide the same results:
1
const menu = {
_courses: {
appetizers: [],
mains: [],
desserts: [],
},
get appetizers() {
return this._courses.appetizers;
},
set appetizers(appetizer) {
this._courses.appetizers= appetizer;
}
}
menu.appetizers.push(['food']);
console.log(menu.appetizers);
2
const menu = {
_courses: {
appetizers: [],
mains: [],
desserts: [],
},
}
menu._courses.appetizers.push(['food']);
console.log(menu._courses.appetizers);
1st method uses getter/setter whereas second directly access the property, so my question is..for me 2nd method is more understandable then why getter/setter is "Better" way?
There are many threads proposing why getter/setter should be used, but I was curious to know for the example I have given, which way is better?
Getters and setters are data abstraction and provides an opportunity for validation check.
Sample:
Based on my comment,
I want to create a property Age which should only accept numbers
following is a sample that adds intelligence to the class properties about their possible values. This is one of the simple usecase where getters and setters are helpful
function SimplePerson(name, age) {
this.name = name;
this.age = age;
}
function SmartPerson(name, age) {
// Private validators
function isNameValid(value) {
return /^[a-z']+$/i.test(value);
}
function isAgeValid(value) {
return /\d+/.test(value)
}
// Private property
var name = '';
var age;
Object.defineProperty(this, 'name', {
get: function() {
return name;
},
set: function(value) {
if (isNameValid(value)) {
name = value;
} else {
console.log('Value passed for Name is incorrect')
}
}
})
Object.defineProperty(this, 'age', {
get: function() {
return name;
},
set: function(value) {
if (isAgeValid(value)) {
name = value;
} else {
console.log('Value passed for Age is incorrect')
}
}
})
this.name = name;
this.age = age;
}
var simplePerson = new SimplePerson(123, 'Foo Bar');
var smartPerson = new SmartPerson(123, 'Foo Bar');
console.log(simplePerson, smartPerson)
As getter/setter gives more freedom to write logic before setting/getting the value. I.e. you can keep check of the type of etc.
Why use getters and setters in JavaScript
A difference between using a getter or setter and using a standard function is that getters/setters are automatically invoked on assignment. So it looks just like a normal property but behind the scenes you can have extra logic (or checks) to be run just before or after the assignment.
So if you decide to add this kind of extra logic to one of the existing object properties that is already being referenced, you can convert it to getter/setter style without altering the rest of the code that has access to that property.

JavaScript private members - Without stage 3 presets [duplicate]

This question already has answers here:
Private properties in JavaScript ES6 classes
(41 answers)
Closed 4 years ago.
We have private members in Java and a lot of other Object Oriented Programming languages. Thus the title of the question is clear: How can we have private members in our JavaScript classes?
Let's consider the following example:
// PrivateMemberOwner.js
export default class PrivateMemberOwner {
iAmPrivate () {
console.log("I can not be accessed from Foo class' children!");
}
iAmPublic () {
console.log("Anyone can call me from anywhere!");
}
}
Then in my PrivateMemberOwnerExtension.js:
import PrivateMemberOwner from "./PrivateMemberOwner.js";
export default class PrivateMemberOwnerExtension extends PrivateMemberOwner {
consumer () {
// This one should work just fine:
Foo.iAmPublic();
// This one should throw some sort of error
Foo.iAmPrivate();
}
}
What is the right way of handling these?
In my opinion, having private members in JavaScript should satisfy these conditions:
Being able to call iAmPrivate within the PrivateMemberOwner class. (As stated in the question)
Not being able to call iAmPrivate anywhere outside the class definition. (At least not being able to call it accidentally)
The mechanism should leverage the prototype inheritance feature of JavaScript in order to consume less memory.
With that being said, the new Symbol type introduced in ES6 comes to mind.
Symbols are a primitive type introduced in ECMAScript 6, joining the existing primitive types: strings, numbers, booleans, null, and undefined.
(From Understanding ECMAScript 6 - by Nicholas C. Zakas)
So, let's get to the code:
// PrivateMemberOwner.js
const iAmPrivate = Symbol("iAmPrivate");
export default class PrivateMemberOwner {
[iAmPrivate] (message) {
console.log("I can not be accessed from Foo class' children!", message);
}
iAmPublic () {
console.log("Anyone can call me from anywhere!");
}
iAmPrivateUser () {
this[iAmPrivate]("I can access 'iAmPrivate' just fine.");
}
}
This way, we can have the iAmPrivateUser method access iAmPrivate method and make the children of PrivateMemberOwner class unable to access it. (at least accidental access to it)
Notes
As mentioned above, these kind of members are not fully private and the member [with some effort] can be accessed like this:
// ./PrivateReader.js
import PrivateMemberOwner from "./PrivateMemberOwner.js";
const privateMemberOwner = new PrivateMemberOwner();
const privateMemberOwnerSymbols = Object.getOwnPropertySymbols(privateMemberOwner);
const iWasPrivate = privateMemberOwner[privateMemberOwnerSymbols[0]];
iWasPrivate.call(privateMemberOwner, 'I just gained your access!');
Having private properties can be achieved the same way:
const barSymbol = Symbol('bar');
class Foo {
constructor () {
this[barSymbol] = null;
}
getBar () {
return this[barSymbol];
}
setBar (value) {
this[barSymbol] = value;
}
}

How to access the class itself from within a class without using its name [duplicate]

This question already has answers here:
JS call static method from class
(7 answers)
Closed 4 years ago.
Is it possible to access the class itself inside of a classes function:
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(MyClass.myFunction); // "foo" -- it works when using its name. This is what we want but without using the name
console.log(this.myFunction); //undefined
console.log(this.prototype.myFunction); //Cannot read property 'myFunction' of undefined
}
}
new MyClass();
Is it possible to achieve the same as you do with MyClass.myFunction() and access the static methods without using the name of the class (in this case without using MyClass in this example?
Something like this.master.myFunction() (I’m just making master up here it’s obviously not called master)
JSBin: https://jsbin.com/hawituxosu/1/edit?js,console
Is that even possible? Thank you!
you can use constructor for this
Returns a reference to the Object constructor function that created the instance object
The constructor property has three purposes:
1. Get the class object.
2. Create an new instance
3. Invoke super constructor
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(this.constructor.myFunction);
}
}
new MyClass();
an option you can do here is to call static method inside an instance method and call that instance method
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(MyClass.myFunction); // "foo" -- whith using its name it works. This is what we want but without using the name
console.log(this.constructor.myFunction);
}
myFunction2() {
return this.constructor.myFunction();
}
}
const master = new MyClass();
master.myFunction2();
this.constructor.myFoo
The constructor property helps you here
You could work around getting to the class name using:
this.__proto__.constructor.name // MyClass
class MyClass {
static get myFunction() { return "foo"; }
constructor() {
console.log(eval(this.__proto__.constructor.name + ".myFunction")); //foo
}
}
new MyClass();

Use prototypical inheritance with ES6 [duplicate]

This question already has answers here:
ES6 - declare a prototype method on a class with an import statement
(3 answers)
Closed 5 years ago.
How can we use the class keyword in ES6 to add methods on the fly like we did in ES5?
https://jsfiddle.net/user1212/7c57eou3/
class Person{
constructor(name){
this.name = name;
}
getName(){
return this.name;
}
setName(name){
this.name = name;
}
}
function Company(cName){
this.cName = cName;
}
Company.prototype.getName = function(){
return this.cName;
}
How can Person have a new method added after the class has been defined?
You don't use the class keyword to add further methods. Just like in ES5, you simply assign them to the prototype object:
class Person { … }
…
Object.assign(Person.prototype, { // Object.assign provides a neater syntax
logName() { // but really is the same as Person.prototype.logName = …
console.log(this.name);
},
alertName() {
alert(this.name);
}
});
As others have answered your specific question, you'd use prototype
But just as a reminder, if you are modifying prototype of a class to add methods, maybe you want to use extends syntax and create a "subclass", so you always use the same class logic without touching prototype.
For most programmers that come from other languages is difficult to understand prototype-style classes, so if you could use ES6 only typical class style, I would say go for it. Like this:
class Hello {
constructor(name) {
this.name = name;
}
hello() {
return 'Hello ' + this.name + '!';
}
static sayHelloAll() {
return 'Hello everyone!';
}
}
class HelloWorld extends Hello {
constructor() {
super('World');
}
echo() {
alert(super.hello());
}
}
var hw = new HelloWorld();
hw.echo();
alert(Hello.sayHelloAll());
taken from here

Categories