indefinite call to "set function()" in JavaScript ES6 class - javascript

I am running this simple class in JavaScript but in console it give me a "Maximum call stack size exceeded" error. and help?!?
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
get name() {
return String(this.name);
}
get age() {
return String(this.age);
}
set name(name) {
this.name = name;
}
set age(age) {
this.age = age;
}
}
let p1 = new Person('Ehsan', 23);
this is a screen shot of the console
}

If you want to indicate that the age property should not be directly used, you should use a different property name than the name used by setters and getters. If the property that the setter / getter sets or gets is the same name as the setter or getter, it'll just keep calling itself, resulting in your error.
A common convention is to put an underscore before the property:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
get name() {
return String(this._name);
}
get age() {
return String(this._age);
}
set name(name) {
this._name = name;
}
set age(age) {
this._age = age;
}
}
let p1 = new Person('Ehsan', 23);
console.log(p1.age);
p1.age = 32;
console.log(p1.age);
But the property is still viewable by consumers via p1._age - if you wanted to prevent that, you can make it more private with a closure and WeakMap:
const Person = (() => {
const privateVals = new WeakMap();
return class Person {
constructor(name, age) {
const privateObj = {};
privateObj.name = name;
privateObj.age = age;
privateVals.set(this, privateObj);
}
get name() {
return String(privateVals.get(this).name);
}
get age() {
return String(privateVals.get(this).age);
}
set name(name) {
privateVals.get(this).name = name;
}
set age(age) {
privateVals.get(this).age = age;
}
}
})();
let p1 = new Person('Ehsan', 23);
console.log(p1.age);
p1.age = 32;
console.log(p1.age);

You can't have a getter / setter pair and a field with the same name. this.name = inside the setter will itself call the setter. If you really need a getter / setter, use another field, e.g. this._name = ... But to be honest: Don't use a getter / setter here. If you do person.name = 15 you should rather fix that than trying to do that with getters / setters.

I believe you just have to rename your class variables in your constructor and then you should be good to go?
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
get name() {
return String(this._name);
}
get age() {
return String(this._age);
}
set name(name) {
this._name = name;
}
set age(age) {
this._age = age;
}
}

Related

the incrementAge function is returning undefined/NaN when invoked after defining the new User

sorry, the incrementAge function is returning undefined/NaN when invoked after defining the new User. I am not sure what's wrong
function User(name,age){
this.name = name;
this.age = age;
}
User.prototype.incrementAge = ()=>{
return this.age++;
}
const mike = new User("Mike",20);
console.log(mike.incrementAge());
The correct way to do this is to create a User class and create a method to raise the value of the variable age.
As you can see by calling the increment age method several times the value is added.
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
incrementAge() {
return ++this.age;
}
}
const mike = new User("Mike", 20);
console.log(mike.incrementAge());
console.log(mike.incrementAge());
The solution (by #ChrisG in comments)
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.incrementAge = function () {
return ++this.age;
}
const mike = new User("Mike", 20);
console.log(mike.incrementAge());

Output not correct, unsure of how to fix

I have to have two arguements, name and dept, and made a name and dept instance variable that defaults to name unknown and department unknown, then make the get and set methods for them, but each time I run this it gives me the class name and dept is undefined
Well originally I didn't have it in a class and had it as a straight const function, and it was working, but when I couldn't reference it properly in another file, I was told they need to be put in a class which I tried, and now its not giving the output I need.
class Faculty {
constructor(name, dept) {
this.name = "name unknown";
this.dept = "department unknown";
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
}
Faculty.toString = function () {
return this.name.concat(" of ").concat(this.dept);
}
//Faculty.name = "Testname";
//Faculty.dept = "Electronic Technology";
console.log(Faculty.toString());
When ran it gives Faculty of undefined, even when I try to define name, it still just says Faculty, though I need it to be of that defaults to name unknown of department unknown unless set otherwise.
Here's how I would put it (and it works)
EDIT : Since this answer was chosen, I will add here the good elements pointed by the other answers
const DEFAULT_NAME = "name unknown";
const DEFAULT_DEPT = "department unknown";
class Faculty {
constructor(name = DEFAULT_NAME, dept DEFAULT_DEPT) {
this.name = name;
this.dept = dept;
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
toString() {
return `${this.name} of ${this.dept}`;
}
}
const f = new Faculty("Faculty", "Department");
console.log(f.toString());
Also you can use the default params like this :
class Faculty {
constructor(name = 'name unknown', dept = 'department unknown') {
this.name = name;
this.dept = dept;
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
toString() {
return `${this.name} of ${this.dept}`;
}
}
const f = new Faculty('Alex', 'Maths');
console.log(f.toString());
For one, you'd have to create a new instance of Faculty in order to call one of its class methods.
Second, there's no need to declare the toString method outside of the class; it can be included just as the others.
Third, I think the method itself could be simplified/clarified by using template literals.
const DEFAULT_NAME = "name_unknown";
const DEFAULT_DEPARTMENT = "department_unknown";
class Faculty {
constructor(name, dept) {
this.name = name || DEFAULT_NAME;
this.dept = dept || DEFAULT_DEPARTMENT;
}
getName() {
return this.name;
}
getDept() {
return this.dept;
}
setName(name) {
this.name = name;
}
setDept(dept) {
this.dept = dept;
}
toString() {
return `${this.name} of ${this.dept}`
}
}
//With name and department
const faculty = new Faculty("John Smith", "Department XYZ");
console.log(faculty.toString());
//Without name and department
const faculty_default = new Faculty();
console.log(faculty_default.toString());

ES6: Can a getter inherit from a parent if the child overrides the setter? [duplicate]

I'm wondering if the following is in compliance with the ES6 spec:
class X {
constructor(name) {
this._name = name;
}
get name() {
return this._name;
}
set name(name) {
this._name = name + "X";
}
}
class Y extends X {
constructor(name) {
super(name);
}
set name(name) {
super.name = name;
this._name += "Y";
}
}
The idea is that let y = new Y(""); y.name = "hi" should result in y.name === "hiXY" being true.
As far as I can tell, this doesn't work in Chrome with the ES6 flag turned on. It also doesn't work using Babel with the es2015 flag. Is using super.name = ... in an inherited setter not part of the ES6 spec? Or is this a bug in the implementation of Babel?
class Y extends X {
constructor(name) {
super(name);
}
set name(name) {
super.name = name;
this._name += "Y";
}
}
will override the name properly with an accessor for just the setter, with no getter. That means your y.name === "hiXY" will fail because y.name will return undefined because there is no getter for name. You need:
class Y extends X {
constructor(name) {
super(name);
}
get name(){
return super.name;
}
set name(name) {
super.name = name;
this._name += "Y";
}
}

Nested classes in AdWords Script (JavaScript) - access parent properties [duplicate]

How do you access the this object from another object instance?
var containerObj = {
Person: function(name){
this.name = name;
}
}
containerObj.Person.prototype.Bag = function(color){
this.color = color;
}
containerObj.Person.prototype.Bag.getOwnerName(){
return name; //I would like to access the name property of this instance of Person
}
var me = new Person("Asif");
var myBag = new me.Bag("black");
myBag.getOwnerName()// Want the method to return Asif
Don't put the constructor on the prototype of another class. Use a factory pattern:
function Person(name) {
this.name = name;
}
Person.prototype.makeBag = function(color) {
return new Bag(color, this);
};
function Bag(color, owner) {
this.color = color;
this.owner = owner;
}
Bag.prototype.getOwnerName = function() {
return this.owner.name;
};
var me = new Person("Asif");
var myBag = me.makeBag("black");
myBag.getOwnerName() // "Asif"
Related patterns to deal with this problem: Prototype for private sub-methods, Javascript - Is it a bad idea to use function constructors within closures?

setters and getters in javascript

I am trying to learn classes and setters and getters in JavaScript .. but my code isn't working .. it alerts undefined .. here is my code
function Person () {
name:"something"
Person.prototype = {
get Name (){
return name;
},
set Name (val){
this.name = val;
}
};
};
var person = new Person();
alert(person.name);
This is the right way to set getters and setters in your example:
function Person () {
this.name = "something";
}
Person.prototype = {
get Name() {
return this.name;
},
set Name(val) {
this.name = val;
}
};
var person = new Person();
person.Name = 'example';
alert(person.name);
JS is based on prototypes, then u can define propertys:
function Person(){
this._name = '';
}
Object.defineProperty(Person.prototype, "name", {
get: function(){
return this._name;
},
set: function(value){
this._name= value;
},
enumerable:true,
configurable: true
});
Then u can set or get property "name"
var p = new Person()
p.name = 'Stackoverflow'
alert(p.name) // Stackoverflow
In ES6 u can use the keyword class, example:
class Person {
constructor() {
this.name = '';
}
}

Categories