31
votes

I am trying to learn get and set in JavaScript object for that I tried

function ab(n){this.name=n;}; 
var c= new ab("abcde");  
console.log(c);
Object.defineProperty(c, 'name', {
    get: function() {
        return name;
    },
    set: function(Name) {
       this.name = Name;
        }
}); 
c.name="xyz";  
console.log(c.name); 

Here I am first making object using constructor and then using get and set. But i am getting error "Maximum call stack size exceeded". I am not getting the reason of This Error . Thanks for help

4

4 Answers

40
votes

I think it has already been explained, that this.name = Name in the setter calls again the setter, wich leads to an infinite recursion.

How about this aproach:

function Ab(_name){
    Object.defineProperty(this, "name", {
        //enumerable: true, //maybe?
        get: function(){ return _name },
        set: function(value){ _name = value }
    });
}

var c = new Ab("abcde");
console.log(c, c.name);

Or the prototypal-approach
downside: the private property _name is a public

function Ab(n){
    this.name = n;
}
Object.defineProperty(Ab.prototype, "name", {
    get: function(){ return this._name },
    set: function(value){ this._name = value }
});

Or ES6
pretty much the same thing as the prototypal aproach

class Ab{
    constructor(n){
        this.name = n;
    }

    get name(){ return this._name },
    set name(value){ this._name = value }
}
3
votes

The set syntax binds an object property to a function to be called when there is an attempt to set that property.

You dont need to do this.name = Name; inside set function. This recursively triggers the setter causing stack overflow. In fact you dont need a setter altogether in this case. Use setter only if, you have to do some extra work when the the property is set or modified.

More

1
votes

You're naming your property (name) same as the backing field in the object that you're adding the property to. Additionally, this operator inside the set is referring to the wrong scope (specifically, it's scoped to the property, not the object); due to that, you're recursively setting the name property, causing a stack overflow exception.

You can modify your code as follows:

function myObject(n){ 
    this.nameValue = n;

    Object.defineProperty(this, 'name', {
         get: function() {
            return this.nameValue;
        },
        set: function(value) {
           this.nameValue = value;
        }
    }); 
}

var c = new myObject("foo");  
console.log(c.name);       //logs "foo"

c.name="bar";  
console.log(c.name);      //logs "bar"

The this keyword in get and set components of the name property now refers to the object defined by myObject function, because Object.defineProperty call is within that function.

0
votes

You used Object.defineProperty() wrong. It should be called upon an uninitialized Object, ab in this case.

Object.defineProperty(ab, 'name', { //.. };